以编程方式将列和行添加到 WPF 数据网格

我想知道我们应该如何在 WPF 中以编程方式向 DataGrid 添加列和行。就像我们以前在窗口表单里做的那样。创建表的列和行,并将其绑定到 DataGrid。

我没有。我需要在 DataGrid 中绘制的行和列,以便用户可以编辑单元格中的数据。

269555 次浏览

以编程方式添加行:

DataGrid.Items.Add(new DataItem());

以编程方式添加列:

DataGridTextColumn textColumn = new DataGridTextColumn();
textColumn.Header = "First Name";
textColumn.Binding = new Binding("FirstName");
dataGrid.Columns.Add(textColumn);

有关更多信息,请查看 WPF DataGrid 讨论板上的 这篇文章

我找到了一个在运行时添加列并绑定到 DataTable的解决方案。

不幸的是,以这种方式定义的47个列对于我来说绑定到数据的速度不够快。有什么建议吗?

谢谢

<DataGrid
Name="dataGrid"
AutoGenerateColumns="False"
ItemsSource="{Binding}">
</DataGrid>

Xaml.cs 使用 System.Windows.Data;

if (table != null) // table is a DataTable
{
foreach (DataColumn col in table.Columns)
{
dataGrid.Columns.Add(
new DataGridTextColumn
{
Header = col.ColumnName,
Binding = new Binding(string.Format("[{0}]", col.ColumnName))
});
}


dataGrid.DataContext = table;
}

如果您已经有了数据绑定,那么 John Myczek 的答案是完整的。
如果没有,你至少有2个选项,我知道如果你想指定你的数据源。(不过,我不确定这是否在 符合大多数指导方针,如 MVVM)

选项1: 就像 JohnB 说的那样,但是我认为你应该使用你自己定义的集合 而不是弱类型的 DataTable (无意冒犯,但您无法从 编码每列所代表的内容)

Xaml.cs

DataContext = myCollection;


//myCollection is a `ICollection<YourType>` preferably
`ObservableCollection<YourType>


- option 2) Declare the name of the Datagrid in xaml


<WpfToolkit:DataGrid Name=dataGrid}>

Xaml.cs

CollectionView myCollectionView =
(CollectionView)CollectionViewSource.GetDefaultView(yourCollection);
dataGrid.ItemsSource = myCollectionView;

如果您的类型定义了一个属性 名字,那么您可以执行 John Myczek 指出的操作。

DataGridTextColumn textColumn = new DataGridTextColumn();
dataColumn.Header = "First Name";
dataColumn.Binding = new Binding("FirstName");
dataGrid.Columns.Add(textColumn);

如果您不知道将需要在 dataGrid 中显示的属性,那么这显然不起作用,但是如果是这种情况,您将有更多的问题需要处理,我相信这已经超出了范围。

编辑 : 对不起,我不再有下面提到的代码了。这是一个简洁的解决方案,尽管很复杂。


我发布了一个示例项目,该项目描述了如何使用 PropertyDescriptor 和 lambda 委托与动态观察集和 DynamicObject 一起填充带有 强类型列定义的网格。

可以在运行时 动态的添加/删除列。如果数据不是具有已知类型的对象,则可以创建一个数据结构,该结构允许任意数量的列进行访问,并为每个“列”指定一个 PropertyDescriptor。

例如:

IList<string> ColumnNames { get; set; }
//dict.key is column name, dict.value is value
Dictionary<string, string> Rows { get; set; }

您可以这样定义列:

var descriptors= new List<PropertyDescriptor>();
//retrieve column name from preprepared list or retrieve from one of the items in dictionary
foreach(var columnName in ColumnNames)
descriptors.Add(new DynamicPropertyDescriptor<Dictionary, string>(ColumnName, x => x[columnName]))
MyItemsCollection = new DynamicDataGridSource(Rows, descriptors)

或者更好,如果是真实物体的话

public class User
{
public string FirstName { get; set; }
public string LastName{ get; set; }
...
}

可以指定强类型列(与数据模型相关) :

var propertyDescriptors = new List<PropertyDescriptor>
{
new DynamicPropertyDescriptor<User, string>("First name", x => x.FirstName ),
new DynamicPropertyDescriptor<User, string>("Last name", x => x.LastName ),
...
}


var users = retrieve some users


Users = new DynamicDataGridSource<User>(users, propertyDescriptors, PropertyChangedListeningMode.Handler);

然后您只需绑定到 Users 集合,并在指定列时自动生成列。传递给属性描述符的字符串是列标题的名称。在运行时,您可以向“用户”中添加更多的 PropertyDescriptors,向网格中添加另一列。

试试这个,它工作100% : 以编程方式添加列和行: 您首先需要创建条目类:

public class Item
{
public int Num { get; set; }
public string Start { get; set; }
public string Finich { get; set; }
}


private void generate_columns()
{
DataGridTextColumn c1 = new DataGridTextColumn();
c1.Header = "Num";
c1.Binding = new Binding("Num");
c1.Width = 110;
dataGrid1.Columns.Add(c1);
DataGridTextColumn c2 = new DataGridTextColumn();
c2.Header = "Start";
c2.Width = 110;
c2.Binding = new Binding("Start");
dataGrid1.Columns.Add(c2);
DataGridTextColumn c3 = new DataGridTextColumn();
c3.Header = "Finich";
c3.Width = 110;
c3.Binding = new Binding("Finich");
dataGrid1.Columns.Add(c3);


dataGrid1.Items.Add(new Item() { Num = 1, Start = "2012, 8, 15", Finich = "2012, 9, 15" });
dataGrid1.Items.Add(new Item() { Num = 2, Start = "2012, 12, 15", Finich = "2013, 2, 1" });
dataGrid1.Items.Add(new Item() { Num = 3, Start = "2012, 8, 1", Finich = "2012, 11, 15" });
}

我也有同样的问题。向 WPFDataGrid添加新行需要一个技巧。DataGrid依赖于项对象的属性字段。ExpandoObject支持动态添加新属性。下面的代码解释了如何做到这一点:

// using System.Dynamic;


DataGrid dataGrid;


string[] labels = new string[] { "Column 0", "Column 1", "Column 2" };


foreach (string label in labels)
{
DataGridTextColumn column = new DataGridTextColumn();
column.Header = label;
column.Binding = new Binding(label.Replace(' ', '_'));


dataGrid.Columns.Add(column);
}


int[] values = new int[] { 0, 1, 2 };


dynamic row = new ExpandoObject();


for (int i = 0; i < labels.Length; i++)
((IDictionary<String, Object>)row)[labels[i].Replace(' ', '_')] = values[i];


dataGrid.Items.Add(row);

//编辑:

请注意,这不是组件应该如何使用的方式,但是,如果您只有编程生成的数据(例如,在我的例子中: 一系列特性和神经网络输出) ,那么它将大大简化。

如果您已经有了数据绑定,那么 John Myczek 的答案是完整的。 如果没有,你至少有2个选项,我知道如果你想指定你的数据源。(然而,我不确定这是否符合大多数指导方针,如 MVVM)

然后您只需绑定到 Users 集合,并在指定列时自动生成列。传递给属性描述符的字符串是列标题的名称。在运行时,您可以向“用户”中添加更多的 PropertyDescriptors,向网格中添加另一列。

在 CodeBehind 中将 DataTable 绑定到 DataGridTextColumn 谢谢

<DataGrid
Name="TrkDataGrid"
AutoGenerateColumns="False"
ItemsSource="{Binding}">
</DataGrid>

Xaml.cs

  foreach (DataColumn col in dt.Columns)
{
TrkDataGrid.Columns.Add(
new DataGridTextColumn
{
Header = col.ColumnName,
Binding = new Binding(string.Format("[{0}]", col.ColumnName))
});
}


TrkDataGrid.ItemsSource= dt.DefaultView;