[WPF 一問一答] WPF DataGrid 如何增加列?

來源:互聯網
上載者:User

問:

WPF的項目,客戶希望給DataGrid添加列(當然,也要能添加行了),而且不是只添一次,而是不斷的增加列。例如,現有的列名是“規則一”、“規則二”,他們希望能夠不斷添加新的規則(每按一次鍵添加新的一列),然後再在DataGrid裡輸入、修改。就是要像Access一樣。

一般的DataGrid是綁定到指定的ObservableCollection, 而每一列實際是綁定到the property of the data source. 像現在這樣的要求,該如何綁定才行呢?

我試著先把資料放到一個DataTable裡,然後DataGrid binding to this DataTable,make "AutomaticGenerateColumn = True"。然後每次使用者選擇添加,就添加到DataTable裡,希望DataGrid能根據DataTable的變化自動產生新列,但是DataGrid不能自動更新,不知道為什麼,另外這種在中間加DataTable的辦法好像也不是太好,希望能找到更聰明點的辦法。

[原帖:http://social.microsoft.com/Forums/zh-CN/wpfzhchs/thread/69ac1292-9512-4bd3-b691-795f64cb0aa0]

 

----------------------------------

答:

WPF中所有的ItemsControl只支援一維的資料結構,簡單理解,我們的ListBox,ListView, ComboBox, 甚至DataGrid 都是僅支援一個維度集合。這裡你要問了,為啥DataGrid有行和列? 其實我們是這麼設計的,一個維度嵌套在另一個維度中,就能夠形成二維的集合結構,但是對於DataGrid來說,對於他能夠直接操作的還是第一維的DataGridRow。 我們集合中每一行元素或者講每一個元素都是會被一個 DataGridRow封裝好放入DataGrid。 然後在DataGridRow還會有進一步的每個元素的各個屬性的封裝 DataGridCell。 為什麼我要講這個,是因為我要告訴你,在WPF中,一旦這個DataGrid顯示出來的,他的可視樹中是根本沒有所謂列的概念的,他的可視樹裡面只有行和儲存格的概念。所以你的第一個問題,要動態添加列,只有在DataGrid沒有顯示前增加,即在DataGrid的邏輯樹狀結構裡面增加。 或者我們可以動態增加DataGrid所綁定的DataTable的列,然後重新設定DataGrid的綁定,讓DataGrid重新根據資料來源來自動產生列。

所以,我上面已經回答了你的 “一般的DataGrid是綁定到指定的ObservableCollection, 而每一列實際是綁定到the property of the data source. 像現在這樣的要求,該如何綁定才行呢?” 這個問題,是不能實現的。WPF中的DataGrid在綁定後顯示出來了,就不能再加列了,每個明確的類型的屬性是不能隨意增加的。

除非,你的ObservableCollection集合裡面是一個dynamic類型,他可以動態添加屬性,這種類型你可以添加好類型之後,重新設定DataGrid的ItemsSource綁定即可(註:此方法只能用在WPF 4 .Net 4 Framework裡面,參考此文:http://blogs.msdn.com/b/llobo/archive/2009/11/02/new-wpf-feature-binding-to-dynamic-objects.aspx)

程式碼片段:

 

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

 

例子比較複雜,你下載看一下: https://skydrive.live.com/#!/?cid=51b2fdd068799d15&sc=documents&uc=1&id=51B2FDD068799D15%21827

------------------------------------------------------

如果你是選擇DataTable作為資料來源,那就相對簡單一點,你在DataTable裡面動態增加了列之後,和新列的每一行資料之後,你可以先設定DataGrid.ItemsSource = null; 然後再重新設定ItemsSource到你的DataTable:

XAML:

  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <StackPanel Orientation="Horizontal">
      <Button Content="Add Column" Click="AddColumn_Click" Margin="5"/>
      <Button Content="Add Data" Click="AddData_Click" Margin="5"/>
    </StackPanel>
    <DataGrid x:Name="dataGrid" AutoGenerateColumns="True" Grid.Row="1"/>
  </Grid>
 

C#:

  public partial class MainWindow : Window
  {
    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;
    }
  }

 

下載:https://skydrive.live.com/#!/?cid=51b2fdd068799d15&sc=documents&uc=1&id=51B2FDD068799D15%21825

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.