繁体   English   中英

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

[英]programmatically add column & rows to WPF Datagrid

我想知道我们应该如何以编程方式将列和行添加到 WPF 中的 DataGrid。 我们在 windows forms 中使用的方式。 创建表列和行,并将其绑定到 DataGrid。

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

以编程方式添加一行:

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

以编程方式添加列:

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

查看 WPF DataGrid 讨论板上的这篇文章了解更多信息。

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

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

我有同样的问题。 向 WPF DataGrid添加新行需要一个技巧。 DataGrid依赖于项目 object 的属性字段。 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);

//编辑:

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

我找到了一个在运行时添加列并绑定到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;
}

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


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

列可以在运行时动态添加/删除。 如果您的数据不是具有已知类型的 object,您可以创建一个数据结构,该结构可以通过任意数量的列进行访问,并为每个“列”指定一个 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);

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

如果您已经有了数据绑定,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 中显示的属性,这显然是行不通的,但如果是这种情况,您将有更多问题需要处理,我相信 scope 不在此列。

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

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

将 DataTable 绑定到 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;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM