我是WPF的新手。我只想知道如何以编程方式将列和行添加到WPF中的DataGrid。我们过去常常在Windows窗体中执行此操作。创建表列和行,并将其绑定到DataGrid。
我相信WPF DataGrid与ASP.net和Windows窗体中使用的有点不一样(如果我错了,请纠正我)。
我需要在DataGrid中绘制行数和列数,以便用户可以编辑单元格中的数据。
答案 0 :(得分:67)
以编程方式添加一行:
DataGrid.Items.Add(new DataItem());
以编程方式添加列:
DataGridTextColumn textColumn = new DataGridTextColumn();
textColumn.Header = "First Name";
textColumn.Binding = new Binding("FirstName");
dataGrid.Columns.Add(textColumn);
查看WPF DataGrid讨论板上的this post以获取更多信息。
答案 1 :(得分:27)
试试这个,它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" });
}
答案 2 :(得分:20)
我遇到了同样的问题。向WPF DataGrid
添加新行需要一个技巧。 DataGrid
依赖于item对象的属性字段。 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);
//编辑:
请注意,这不是组件应该如何使用的方式,但是,如果您只有编程生成的数据(例如,在我的情况下:一系列功能和神经网络输出),它会简化很多。
答案 3 :(得分:11)
我找到了一个在运行时添加列的解决方案,并绑定到DataTable
。
不幸的是,有47列以这种方式定义,它不能足够快地绑定到数据上。有什么建议吗?
<强> XAML 强>
<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;
}
答案 4 :(得分:4)
修改:抱歉,我不再拥有下面提到的代码了。这是一个很好的解决方案,虽然很复杂。
我发布了一个示例项目,描述了如何使用带有动态ObservableCollection和DynamicObject的PropertyDescriptor和lambda委托,用强类型列定义填充网格。
可以在运行时动态添加/删除列。如果您的数据不是具有已知类型的对象,则可以创建一个数据结构,该数据结构将允许任意数量的列进行访问,并为每个“列”指定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,将另一列添加到网格中。
答案 5 :(得分:3)
如果您已经有数据绑定,那么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;
如果您的类型定义了属性 FirstName ,则可以执行John Myczek指出的操作。
DataGridTextColumn textColumn = new DataGridTextColumn();
dataColumn.Header = "First Name";
dataColumn.Binding = new Binding("FirstName");
dataGrid.Columns.Add(textColumn);
如果您不知道需要在dataGrid中显示的属性,这显然不起作用,但如果是这种情况,您将遇到更多问题,我认为这超出了范围。< / p>
答案 6 :(得分:0)
要将数据表绑定到CodeBehind中的DataGridTextColumn xaml
<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;
答案 7 :(得分:-1)
如果您已经有数据绑定,那么John Myczek的答案就完成了。 如果不是,您至少有两个我知道的选项,如果您想指定数据来源。 (但我不确定这是否符合大多数指南,如MVVM)
的
然后,您只需绑定到Users集合,并在指定列时自动生成列。传递给属性描述符的字符串是列标题的名称。在运行时,您可以向“用户”添加更多PropertyDescriptors,将另一列添加到网格中。的