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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/704724/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 14:07:45  来源:igfitidea点击:

programmatically add column & rows to WPF Datagrid

c#wpfdatagridwpf-controlssilverlight-2.0

提问by Andy

I'm new to WPF. I just want to know how should we add columns and rows programmatically to a DataGrid in WPF. The way we used to do it in windows forms. create table columns and rows, and bind it to DataGrid.

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

I believe WPF DataGrid is bit different the one used in ASP.net and Windows form (correct me if I am wrong).

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

I have No. of rows and columns which I need to draw in DataGrid so that user can edit the data in the cells.

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

回答by John Myczek

To programatically add a row:

以编程方式添加一行:

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

To programatically add a column:

要以编程方式添加列:

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

Check out this poston the WPF DataGrid discussion board for more information.

查看WPF DataGrid 讨论板上的这篇文章以获取更多信息。

回答by JohnB

I found a solution that adds columns at runtime, and binds to a DataTable.

我找到了一个在运行时添加列并绑定到DataTable.

Unfortunately, with 47 columns defined this way, it doesn't bind to the data fast enough for me. Any suggestions?

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

xaml

xml

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

xaml.csusing System.Windows.Data;

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

回答by HCP

If you already have the databinding in place John Myczek answer is complete.
If not you have at least 2 options I know of if you want to specify the source of your data. (However I am not sure whether or not this is in line with most guidelines, like MVVM)

如果您已经有了数据绑定,那么 John Myczek 的答案就完成了。
如果不是,如果您想指定数据源,我知道至少有 2 个选项。(但是我不确定这是否符合大多数指南,例如 MVVM)

option 1:like JohnB said. But I think you should use your own defined collection instead of a weakly typed DataTable (no offense, but you can't tell from the code what each column represents)

选项 1:就像 JohnB 说的那样。但我认为您应该使用自己定义的集合而不是弱类型的 DataTable(没有冒犯,但您无法从代码中分辨出每列代表什么)

xaml.cs

xml文件

DataContext = myCollection;

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

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

        <WpfToolkit:DataGrid Name=dataGrid}>

in xaml.cs

xaml.cs 中

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

If your type has a property FirstNamedefined, you can then do what John Myczek pointed out.

如果您的类型定义了FirstName属性,则您可以按照 John Myczek 指出的进行操作。

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

This obviously doesn't work if you don't know properties you will need to show in your dataGrid, but if that is the case you will have more problems to deal with, and I believe that's out of scope here.

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

回答by doblak

edit: sorry, I no longer have the code mentioned below. It was a neat solution, although complex.

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



I posted a sample project describing how to use PropertyDescriptor and lambda delegates with dynamic ObservableCollection and DynamicObject to populate a grid with strongly-typedcolumn definitions.

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

Columns can be added/removed at runtime dynamically. If your data is not a object with known type, you could create a data structure that would enable access by any number of columns and specify a PropertyDescriptor for each "column".

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

For example:

例如:

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

You can define columns this way:

您可以通过以下方式定义列:

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) 

Or even better, in case of some real objects

或者甚至更好,如果是一些真实的物体

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

You can specify columns strongly typed (related to your data model):

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

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

Then you just bind to Users collections and columns are autogenerated as you speficy them. Strings passed to property descriptors are names for column headers. At runtime you can add more PropertyDescriptors to 'Users' add another column to the grid.

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

回答by aminescm

try this , it works 100 % : add columns and rows programatically : you need to create item class at first :

试试这个,它 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" });

        }

回答by Bartek Dzieńkowski

I had the same problem. Adding new rows to WPF DataGridrequires a trick. DataGridrelies on property fields of an item object. ExpandoObjectenables to add new properties dynamically. The code below explains how to do it:

我有同样的问题。向 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);

//edit:

//编辑:

Note that this is not the way how the component should be used, however, it simplifies a lot if you have only programmatically generated data (eg. in my case: a sequence of features and neural network output).

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

回答by Senar

If you already have the databinding in place John Myczek answer is complete. If not you have at least 2 options I know of if you want to specify the source of your data. (However I am not sure whether or not this is in line with most guidelines, like MVVM)

如果您已经有了数据绑定,那么 John Myczek 的答案就完成了。如果不是,如果您想指定数据源,我知道至少有 2 个选项。(但是我不确定这是否符合大多数指南,例如 MVVM)

Then you just bind to Users collections and columns are autogenerated as you speficy them. Strings passed to property descriptors are names for column headers. At runtime you can add more PropertyDescriptors to 'Users' add another column to the grid. 然后,您只需绑定到用户集合,并在您指定它们时自动生成列。传递给属性描述符的字符串是列标题的名称。在运行时,您可以向“用户”添加更多的 PropertyDescriptor,向网格添加另一列。

回答by Maghalakshmi Saravana

To Bind the DataTable into the DataGridTextColumn in CodeBehindxaml

将 DataTable 绑定到 CodeBehind xaml 中的 DataGridTextColumn

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

xaml.cs

xml文件

  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;