以声明方式将行和控件添加到 WPF 中的网格



好吧,我的最后一个问题除了反对票之外没有得到任何回应,所以我将分解这个问题,一次问一个基本问题。

我有一个 WPF 应用程序,其中有一个网格(不是数据网格)。现在我想在运行时向其添加行。在这些行中的每一行中,都有一个控件,如文本框或组合框。我知道这可以通过RowDefinitions.Add(New RowDefinition())来完成,然后向行中的每个单元格添加单独的控件,就像我们在WinForms的TableLayoutPanel中所做的那样。但我正在寻找一个更优雅的解决方案,当单击按钮或触发事件时,所有控件及其事件处理程序都将添加到 Grid 新行中的相应单元格中。有什么简单的方法可以做到吗?

附言我还需要根据需要删除行,如果这是这里的一个因素。删除的行并不总是最后一行。

通常,最好使用 DataGrid 来显示具有重复行的数据,而不是a 网格。但是,如果您有特殊原因需要使用网格,我使用网格附加了一个代码示例,在每行中显示一个文本框、一个组合框和一个 DeleteButton。添加按钮允许在底部添加新行,每行上的删除按钮允许删除该行。

XAML:

<Window x:Class="GridAddRow.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:GridAddRow"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
  <DockPanel>
    <Grid Name="MainGrid" DockPanel.Dock="Top"/>
    <Button  DockPanel.Dock="Top" Name="AddButton" Content="Add"/>
    <Rectangle Fill="Gainsboro"/>
  </DockPanel>
</Window>

C#:

using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
namespace GridAddRow {
  public partial class MainWindow: Window {
    int textCol, comboBoxCol, buttonCol;
    public MainWindow() {
      InitializeComponent();
      //initialise MainGrid, i.e. define columns, could be done in XAML
      addCol(out textCol, new GridLength(100));
      addCol(out comboBoxCol, GridLength.Auto);
      addCol(out buttonCol, GridLength.Auto);
      //initialise grid content, usually read from a db
      addRow("Some Text", 1);
      addRow("Another String", 3);
      AddButton.Click += AddButton_Click;
    }
    private void addCol(out int textCol, GridLength gridLength) {
      textCol = MainGrid.ColumnDefinitions.Count;
      MainGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = gridLength });
    }
    List<TextBox> textBoxes = new List<TextBox>();
    List<ComboBox> comboBoxes = new List<ComboBox>();
    private void addRow(string textBoxString, int comboBoxIndex) {
      int rowId = MainGrid.RowDefinitions.Count;
      MainGrid.RowDefinitions.Add(new RowDefinition());
      TextBox textBox = new TextBox { Text = textBoxString };
      textBoxes.Add(textBox);
      addControl(textBox, rowId, textCol);
      textBox.TextChanged += TextBox_TextChanged;
      ComboBox comboBox = new ComboBox {SelectedIndex= comboBoxIndex };
      comboBox.Items.Add(new ComboBoxItem {Content="0" });
      comboBox.Items.Add(new ComboBoxItem { Content="1" });
      comboBox.Items.Add(new ComboBoxItem { Content="2" });
      comboBox.Items.Add(new ComboBoxItem { Content="3" });
      comboBoxes.Add(comboBox);
      addControl(comboBox, rowId, comboBoxCol);
      comboBox.SelectionChanged += ComboBox_SelectionChanged;
      Button deleteRowButton = new Button {Content = "Delete"};
      addControl(deleteRowButton, rowId, buttonCol);
      deleteRowButton.Click += DeleteRowButton_Click;
    }
    private void addControl(Control control, int rowId, int textCol) {
      control.Tag = rowId;
      MainGrid.Children.Add(control);
      Grid.SetRow(control, rowId);
      Grid.SetColumn(control, textCol);
    }
    private void TextBox_TextChanged(object sender, TextChangedEventArgs e) {
      TextBox textbox = (TextBox)sender;
      int rowid = (int)textbox.Tag;
      //do something here. 
    }
    private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) {
      ComboBox comboBox = (ComboBox)sender;
      int rowid = (int)comboBox.Tag;
      //do something here. 
    }
    private void DeleteRowButton_Click(object sender, RoutedEventArgs e) {
      Button deleteButton = (Button)sender;
      int rowid = (int)deleteButton.Tag;
      MainGrid.Children.Remove(deleteButton);
      TextBox textbox = textBoxes[rowid];
      MainGrid.Children.Remove(textbox);
      textBoxes.RemoveAt(rowid);
      ComboBox comboBox = comboBoxes[rowid];
      MainGrid.Children.Remove(comboBox);
      comboBoxes.RemoveAt(rowid);
    }
    private void AddButton_Click(object sender, RoutedEventArgs e) {
      addRow("", 1);
    }
  }
}

说"你应该使用 MVVM"基本上只是意味着你应该创建一个类,该类对于你在窗口中使用的每个控件(文本框、组合框)都有一个属性。使用要显示的数据创建该类的集合,然后将其绑定到 DataGrid,该网格将显示数据并提供许多功能,您必须在使用 Grid 时自行编程。有关更多详细信息,请参阅我的文章:使用绑定设置 WPF 数据网格格式指南

最新更新