以编程方式将列和行添加到WPF Datagrid


75

我是WPF的新手。我只想知道我们应该如何以编程方式向WPF中的DataGrid添加列和行。我们过去在Windows窗体中执行此操作的方式。创建表的列和行,并将其绑定到DataGrid。

我相信WPF DataGrid与ASP.net和Windows表单中使用的有点不同(如果我错了,请纠正我)。

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

Answers:


74

要以编程方式添加行:

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

以编程方式添加列:

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

在WPF DataGrid讨论板上查看此帖子以获取更多信息。


7
-1:因为显示了非常简单的部分,但没有显示如何将数据实际绑定到那些在运行时添加的列。我确定Andy希望构建一个显示某些数据而不仅仅是列名的应用程序。
2011年

只需在DataGridTextColumn上设置属性即可。我更新了答案。
John Myczek 2011年

+1:我确认可以,谢谢。我还发现,当您添加方括号时,即Binding("[FirstName]") 在下面看到我以前的回答,它可以工作,但是在绑定大型数据集时,它的速度要慢得多。
JohnB 2011年

1
作为DataItem对象,它的外观如何?
C4d

有什么办法可以使用此代码添加多列标题吗?
丹尼斯,

30

尝试一下,它可以100%工作:以编程方式添加列和行:首先需要创建item类:

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" });

        }

有什么办法可以使用此代码添加多列标题吗?
丹尼斯

24

我有同样的问题。向WPF添加新行DataGrid需要技巧。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);

//编辑:

请注意,这并不是应如何使用组件的方式,但是,如果您仅以编程方式生成的数据(例如,在我的情况下:一系列特征和神经网络输出),它将大大简化。


@bartek-dzieńkowski很棒
Mahdi Khalili

12

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

不幸的是,用这种方式定义了47列,它对我的​​绑定速度不够快。有什么建议?

a

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

使用System.Windows.Data的xaml.cs ;

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;
}

那时您找到任何解决方案了吗?
321X 2011年

2
为什么在绑定路径中使用“ [{0}]”?它对我不起作用,但是当我只使用不带正方形和小标签的名称时,它是否起作用?
smerlung 2015年

4

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


我发布了一个示例项目,描述了如何将PropertyDescriptor和lambda委托与动态ObservableCollection和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集合,并且在您随意使用它们时列会自动生成。传递给属性描述符的字符串是列标题的名称。在运行时,您可以向“用户”添加更多PropertyDescriptor,向网格中添加另一列。


@doblak我发现这正是我所需要的。您还有解决方案的代码吗?
zhangz

@zhangz更新了答案,有关DynamicPropertyDescriptor
doblak

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中显示的属性,那么这显然是行不通的,但是如果是这样的话,您将有更多的问题需要处理,我认为这超出了范围。


0

将数据表绑定到CodeBehind xaml中的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;

-1

如果您已经具有适当的数据绑定,则John Myczek的答案是完整的。如果没有,我至少知道2个选项,如果您想指定数据源。(但是我不确定这是否符合大多数准则,例如MVVM)

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.