WPF MVVM中动态生成行

时间:2015-02-25 13:01:48

标签: c# wpf xaml mvvm

我正在创建一个包含ComboBox&的数据输入表单。第一行中的少量文本框。我希望在第一行中按最后一个文本框的输入键生成一个具有相同元素的新行。 我如何实现它?是否有任何数据模板或项目模板或任何可用于此数据输入表单的内容。 我还读到了Observable Collection Class& IEnumerable,这可以帮我实现吗?怎么样? 我是WPF&的Newbie MVVM已经做了很多研究,但找不到确切的解决方案。 我已经这样做了,

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="500" Width="420">
<Grid Name="_mainGrid" HorizontalAlignment="Left">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="227"/>
        <ColumnDefinition Width="77" />
        <ColumnDefinition Width="77" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="27"/>
    </Grid.RowDefinitions>
</Grid>
</Window>

我的.CS代码如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Diagnostics;
using System.Reflection;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        int rowIndex, Dr = 0, Cr = 0;
        TextBox PTextBox, DrAmtTextBox, CrAmtTextBox;
        ComboBox Combobox;
        List<TextBox> txtboxParticulars = new List<TextBox>();
        List<TextBox> txtboxDrAmount = new List<TextBox>();
        List<TextBox> txtboxCrAmount = new List<TextBox>();
        List<ComboBox> cmbboxDrCr = new List<ComboBox>();
        public MainWindow()
        {
            InitializeComponent();
            CreateRow();
        }
        public void CreateRow()
        {
            RowDefinition newRow = new RowDefinition();
            newRow.Height = new GridLength(30, GridUnitType.Pixel);
            _mainGrid.RowDefinitions.Insert(_mainGrid.RowDefinitions.Count - 1, newRow);
            rowIndex = _mainGrid.RowDefinitions.Count - 2;
            AddComboBox();
            AddPTextBox();
            AddDrCrTextBox();                        
        }

        public void AddComboBox()
        {
            Combobox = new ComboBox();
            Combobox.Items.Add("Dr.");
            Combobox.Items.Add("Cr.");
            Combobox.SelectedItem = "Dr.";
            Combobox.Height = 25;
            Combobox.Name = "DrCr" + rowIndex.ToString();
            Combobox.SelectionChanged += new SelectionChangedEventHandler(Combobox_SelectionChanged);
            Combobox.KeyUp += new KeyEventHandler(Combobox_KeyUp);
            Grid.SetRow(Combobox, rowIndex);
            Grid.SetColumn(Combobox, 0);
            _mainGrid.Children.Add(Combobox);
            cmbboxDrCr.Add(new ComboBox { Text = Combobox.Name });
            cmbboxDrCr[rowIndex].Text = "Dr.";
            Combobox.Focus();
        }

        void Combobox_KeyUp(object sender, KeyEventArgs e)
        {
            if (Combobox.SelectedItem.ToString() == "Dr.")
            {
                cmbboxDrCr[rowIndex].Text = "Dr.";
                DrAmtTextBox.Visibility = System.Windows.Visibility.Visible;
                CrAmtTextBox.Visibility = System.Windows.Visibility.Hidden;
            }
            else
            {
                cmbboxDrCr[rowIndex].Text = "Cr.";
                DrAmtTextBox.Visibility = System.Windows.Visibility.Hidden;
                CrAmtTextBox.Visibility = System.Windows.Visibility.Visible;
            }
        }

        void Combobox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (Combobox.SelectedItem.ToString() == "Dr.")
            {
                cmbboxDrCr[rowIndex].Text = "Dr.";
                DrAmtTextBox.Visibility = System.Windows.Visibility.Visible;
                CrAmtTextBox.Visibility = System.Windows.Visibility.Hidden;
                PTextBox.Focus();
            }
            else
            {
                cmbboxDrCr[rowIndex].Text = "Cr.";
                DrAmtTextBox.Visibility = System.Windows.Visibility.Hidden;
                CrAmtTextBox.Visibility = System.Windows.Visibility.Visible;
                PTextBox.Focus();
            }
        }

        public void AddPTextBox()
        {
            PTextBox = new TextBox();
            PTextBox.Name = "Particulars" + rowIndex.ToString();
            PTextBox.Height = 25;
            PTextBox.Width = 225;
            Grid.SetRow(PTextBox, rowIndex);
            Grid.SetColumn(PTextBox, 1);
            _mainGrid.Children.Add(PTextBox);
            txtboxParticulars.Add(new TextBox { Text = PTextBox.Name });            
        }

        public void AddDrCrTextBox()
        {
            DrAmtTextBox = new TextBox();
            DrAmtTextBox.Name = "Dr" + rowIndex.ToString();
            DrAmtTextBox.Height = 25;
            DrAmtTextBox.Width = 75;
            DrAmtTextBox.KeyDown += new KeyEventHandler(DrCrAmtTextBox_KeyDown);
            Grid.SetRow(DrAmtTextBox, rowIndex);
            Grid.SetColumn(DrAmtTextBox, 2);
            _mainGrid.Children.Add(DrAmtTextBox);
            txtboxDrAmount.Add(new TextBox { Text = DrAmtTextBox.Name });
            CrAmtTextBox = new TextBox();
            CrAmtTextBox.Name = "Cr" + rowIndex.ToString();
            CrAmtTextBox.Height = 25;
            CrAmtTextBox.Width = 75;
            CrAmtTextBox.Visibility = System.Windows.Visibility.Hidden;
            CrAmtTextBox.KeyDown += new KeyEventHandler(DrCrAmtTextBox_KeyDown);
            Grid.SetRow(CrAmtTextBox, rowIndex);
            Grid.SetColumn(CrAmtTextBox, 3);
            _mainGrid.Children.Add(CrAmtTextBox);
            txtboxCrAmount.Add(new TextBox { Text = DrAmtTextBox.Name });
        }

        void DrCrAmtTextBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                AddDataToList();
                CountDrCr();
                CreateRow();
            }
        }
        void CountDrCr()
        {
            for (int i = 0; i <= rowIndex; i++)
            {
                if (cmbboxDrCr[i].Text == "Dr.")
                {
                    Dr++;
                }
                else
                {
                    Cr++;
                }
            }
        }
        void AddDataToList()
        {
            cmbboxDrCr[rowIndex].Text = Combobox.Text;
            txtboxParticulars[rowIndex].Text = PTextBox.Text;
            txtboxDrAmount[rowIndex].Text = CrAmtTextBox.Text;
            txtboxCrAmount[rowIndex].Text = DrAmtTextBox.Text;
            MessageBox.Show(cmbboxDrCr[rowIndex].Text +" "+ txtboxParticulars[rowIndex].Text + " " + txtboxDrAmount[rowIndex].Text + " " + txtboxCrAmount[rowIndex].Text);
        }

    }
}

我知道这不是正确的方法,所以请帮我用WPF MVVM做这个方法!!!

在完成答案后,我完成了以下

  • 创建了一个DataType

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace DataTemplate
    {
        class YourDataType
        {
            public string DrCr { get; set; }
            public string Particulars { get; set; }
            public float Amount { get; set; }
            public string Narration { get; set; }
        }
    }
    
  • MainWindow.Xaml文件

    <Window x:Class="DataTemplate.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DataTemplate"
        Title="MainWindow" Height="350" Width="750">
    <Grid>
        <ListBox ItemsSource="{Binding YourCollection}">
            <ListBox.ItemTemplate>
                <DataTemplate DataType="{x:Type local:YourDataType}">
                    <StackPanel Orientation="Horizontal">
                        <StackPanel Orientation="Horizontal">
                            <ComboBox SelectedIndex="0">
                                <ComboBoxItem Content="Dr."/>
                                <ComboBoxItem Content="Cr."/>
                            </ComboBox>
                            <TextBox Width="350"/>
                            <TextBox Width="150"/>
                        </StackPanel>
                        <Label Content="Narration"/>
                        <TextBox Width="450"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
    

  • MainWindow.CS文件

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using System.Collections.ObjectModel;
    
    namespace DataTemplate
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            private ObservableCollection<YourDataType> YourCollection;
            public MainWindow()
            {
                InitializeComponent();
                YourCollection.Add(new YourDataType());
            }
         }
      }
    

2 个答案:

答案 0 :(得分:0)

  

虽然非WPF开发人员在代码中构建其UI似乎很自然,但通常如何在WPF中完成。学会在XAML中完成它,你将自己保存许多头痛。

首先创建一种数据类型,例如,我们将其称为YourDataType,其中包含每个&#39;行的所有必需属性。然后声明一个ObservableCollection<YourDataType>属性以将数据绑定到集合控件,让我们将其称为YourCollection。最后,声明一个DataTemplate,用于定义每行的外观:

<ListBox ItemsSource="{Binding YourCollection}">
    <ListBox.ItemTemplate>
        <DataTemplate DataType="{x:Type YourPrefix:YourDataType}">
            <!-- Define your 'row' controls here -->
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

现在要添加一个新的空行,您只需要在数据绑定集合中添加一个新项:

YourCollection.Add(new YourDataType());

有关详细信息,请参阅MSDN上的Data Binding Overview页面。

答案 1 :(得分:0)

您可以使用内部的完整结构(comboBoxand和文本框)创建WPF用户控件,您可以创建此用户控件的单个列表

例如,您可以创建一个与此类似的FormRow.xaml用户控件....

<UserControl x:Class="WPFTEST.FormRow"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-    compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         Width="500" Height="26">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>
        <ComboBox Margin="0"/>
        <TextBox TextWrapping="Wrap" Text="TextBox" Grid.Column="1" Margin="0"/>
        <TextBox TextWrapping="Wrap" Text="TextBox" Grid.Column="2" Margin="0"/>
        <TextBox TextWrapping="Wrap" Text="TextBox" Grid.Column="3" Margin="0"/>
    </Grid>
</UserControl>

您可以添加事件并控制代码隐藏中的模型对象信息.....

在主窗口中,您可以拥有listView或Stack,其中包含此单个控件的实例,每个实例都是模型对象的视图,并保留了访问层次结构....