WPF中DataGrid 动态增加列

在WPF的项目中希望给DataGrid动态添加列,而不是添加行。例如,现有的列名是“规则一”、“规则二”,他们希望能够不断添加新的规则(每按一次键添加新的一列),然后再在DataGrid里输入、修改。就是要像Access一样。

WPF中所有的ItemsControl只支持一维的数据结构,简单理解,我们熟悉的ListBox,ListView, ComboBox, 甚至DataGrid 都是仅支持一个维度的集合。为啥DataGrid有行和列? 其实是一个维度嵌套在另一个维度中,就能够形成二维的集合结构,但是对于DataGrid来说,对于它能够直接操作的还是第一维的DataGridRow。 我们集合中每一行元素或者讲每一个元素都是会被一个 DataGridRow包装好放入DataGrid。 然后在DataGridRow还会有进一步的每个元素的各个属性的包装 DataGridCell。在WPF中,DataGrid的可视树中是根本没有所谓列的概念的,只有行和单元格的概念。所以要动态添加列,只有在DataGrid没有显示前增加,即在DataGrid的逻辑树里面增加。 或者我们可以动态增加DataGrid所绑定的DataTable的列,然后重新设置DataGrid的绑定,让DataGrid重新根据数据源来自动生成列。

不过这里也有一种方式,ObservableCollection集合里面是一个dynamic类型,它可以动态的添加属性,这种类型添加好属性之后,重新设置DataGrid的ItemsSource绑定即可,这种方式很多地方可以找到,代码如下:

 ObservableCollection<dynamic> items = new ObservableCollection<dynamic>();
    public MainWindow()
    {
      InitializeComponent();
 
      for (int i = 0; i < 5; i++)
      {
        dynamic item = new DynamicObjectClass();
        item.A = "Property A value - " + i.ToString();
        item.B = "Property B value - " + i.ToString();
        items.Add(item);
      }
 
      dataGrid.Columns.Add(new DataGridTextColumn() {Header="A", Binding = new Binding("A") });
      dataGrid.Columns.Add(new DataGridTextColumn() {Header="B", Binding = new Binding("B") });
      dataGrid.ItemsSource = items;
    }
 
    private void AddData_Click(object sender, RoutedEventArgs e)
    {
      dynamic item = new DynamicObjectClass();
      item.A="New Item - A";
      item.B="New Item - B";
      items.Add(item);
    }
 
    int newColumnIndex = 1;
    private void AddColumn_Click(object sender, RoutedEventArgs e)
    {
      foreach (DynamicObjectClass item in items)
      {
        item.TrySetMember(new SetPropertyBinder("NewColumn" + newColumnIndex), "New Column Value " + newColumnIndex.ToString());
      }
 
      dataGrid.Columns.Add(new DataGridTextColumn() { Header = "New Column" + newColumnIndex, Binding = new Binding("NewColumn" + newColumnIndex) });
 
      newColumnIndex++;
    }

对应的类及对象如下,每次新增列为属性NewColumn及其对应值:

item

A->Property A value 0

B->Property B value 0

NewColumn1-->New Value1

 

item

A->Property A value 1

B->Property B value 1

NewColumn1-->New Value1

 

item

A->Property A value 2

B->Property B value 2

NewColumn1-->New Value1

item

A->Property A value 3

B->Property B value 3

NewColumn1-->New Value1

item

A->Property A value 4

B->Property B value 4

NewColumn1-->New Value1

 

通过以上也发现,实际上新增的列为item列表下中对象的属性及其值,如果以此看做一列的话,实际上操作的还是item对应的一行。所以,也有第二种方式,即选择DataTable作为数据源,在DataTable里面动态增加了列之后,重新构造每一行数据,设置DataGrid.ItemsSource = null; 然后再重新设置ItemsSource到DataTable。代码大致如下:

  DataTable dt = new DataTable();
    public MainWindow()
    {
      InitializeComponent();
 
      dt.Columns.Add(new DataColumn("Column1"));
      dt.Columns.Add(new DataColumn("Column2"));
 
      DataRow dr;
      for (int i = 0; i < 5; i++)
      {
        dr = dt.NewRow();
        for (int columIndex = 0; columIndex < dt.Columns.Count ; columIndex++)
          dr[columIndex] = i.ToString() + " - " + columIndex.ToString();
        dt.Rows.Add(dr);
      }
 
        dataGrid.ItemsSource = dt.DefaultView;
    }
 
    private void AddData_Click(object sender, RoutedEventArgs e)
    {
      DataRow dr = dt.NewRow();
      for (int columIndex = 0; columIndex < dt.Columns.Count; columIndex++)
        dr[columIndex] = "New Row - " + columIndex.ToString();
      dt.Rows.Add(dr);
    }
 
    int newColumnIndex = 1;
    private void AddColumn_Click(object sender, RoutedEventArgs e)
    {
      dt.Columns.Add(new DataColumn("New Column" + newColumnIndex++));
      for (int i = 0; i < dt.Rows.Count; i++)
      {
        dt.Rows[i][dt.Columns.Count - 1] = i.ToString() + " - New Column";
      }
      dataGrid.ItemsSource = null;
      dataGrid.ItemsSource = dt.DefaultView;
    }

 

  • 1
    点赞
  • 0
    评论
  • 10
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值