好吧,我的最后一个问题除了反对票之外没有得到任何回应,所以我将分解这个问题,一次问一个基本问题。
我有一个 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 数据网格格式指南