2010-06-17 164 views
18

我正在尋找如何以MvvM方式從ToolKit動態創建DataGrid的列。但看起來不可能!WPF MvvM DataGrid動態列

有沒有必要做同樣的事情?

沒有必要創建一個來自DataGrid的用戶控件或其他控件,我只想將網格的ItemSource設置爲我的自定義對象,並且在某些點上我想定義網格的運行時動態列基於對象的種類。

這可能嗎?

歡呼

回答

9

我會說這也許是不是要做得最好的解決方案前言本,不得在某些情況下工作,但你可以給它一個嘗試,看看它是否會爲工作你想要什麼。我只是鞭打它,所以它可能有一些錯誤。它仍然會涉及一些代碼,但它會讓你的模型不瞭解你的觀點。

您需要做的是創建一個擴展屬性,該屬性將允許您綁定DataGrid上的Columns屬性。這是一個我放在一起的例子。

using System.Collections.ObjectModel; 
using System.Collections.Specialized; 
using System.Windows; 
using System.Windows.Controls; 

public static class DataGridExtension 
{ 
    public static ObservableCollection<DataGridColumn> GetColumns(DependencyObject obj) 
    { 
     return (ObservableCollection<DataGridColumn>)obj.GetValue(ColumnsProperty); 
    } 

    public static void SetColumns(DependencyObject obj, ObservableCollection<DataGridColumn> value) 
    { 
     obj.SetValue(ColumnsProperty, value); 
    } 

    public static readonly DependencyProperty ColumnsProperty = 
      DependencyProperty.RegisterAttached("Columns", 
      typeof(ObservableCollection<DataGridColumn>), 
      typeof(DataGridExtension), 
      new UIPropertyMetadata (new ObservableCollection<DataGridColumn>(), 
      OnDataGridColumnsPropertyChanged)); 


    private static void OnDataGridColumnsPropertyChanged(
      DependencyObject d, 
      DependencyPropertyChangedEventArgs e) 
    { 
     if (d.GetType() == typeof(DataGrid)) 
     { 
      DataGrid myGrid = d as DataGrid; 

      ObservableCollection<DataGridColumn> Columns = 
       (ObservableCollection<DataGridColumn>)e.NewValue; 

      if(Columns != null) 
      { 
       myGrid.Columns.Clear(); 

       if (Columns != null && Columns.Count > 0) 
       { 
        foreach (DataGridColumn dataGridColumn in Columns) 
        { 
         myGrid.Columns.Add(dataGridColumn); 
        } 
       } 


       Columns.CollectionChanged += delegate(object sender, 
           NotifyCollectionChangedEventArgs args) 
        { 
         if(args.NewItems != null) 
         { 
         foreach (DataGridColumn column 
           in args.NewItems.Cast<DataGridColumn>()) 
         { 
          myGrid.Columns.Add(column); 
         } 
         } 

         if(args.OldItems != null) 
         { 
         foreach (DataGridColumn column 
           in args.OldItems.Cast<DataGridColumn>()) 
         { 
          myGrid.Columns.Remove(column); 
         } 
         } 
        }; 
      } 
     } 
    } 
} 

然後你把它連接到你的DataGrid這樣的(其中列在你的視圖模型的一個ObservableCollection屬性)

<Controls:DataGrid AutoGenerateColumns="False" 
      DataGridExtension.Columns="{Binding Columns}" /> 

我不知道它會如何,如果您迴應開始添加和刪除列,但它似乎從我的基本測試工作。祝你好運!

+1

上述代碼將在一般情況下完成工作。但是,當您隱藏數據網格並使其再次可見時,它會失敗。由於列屬性將顯示隱藏時有0列,並且在更改列屬性時,回調將被觸發,並且會嘗試再次添加列,但物理列確實存在於數據網格中,因此代碼將有一個例外說不能添加重複的列。 – 2012-08-16 02:34:47

1

有類似的問題,我不想添加另一個依賴屬性。 我的解決方法是組織數據以顯示在DataTable的DataGrid中,並將DataGrid ItemSource屬性綁定到此DataTable(當然AutoGenerateColumns設置爲true)。

它運行良好,DataGrids似乎很滿意DataTable作爲源。

+0

DataGrid.ItemSource不接受DataTable。它說這不是IEnumerable ...(.Net 4.5) – 2014-10-29 15:45:04

+0

我用4.5構建了這個項目,它沒有給我任何錯誤。我綁定了xaml中的datagrid的itemsource:'ItemsSource =「{Binding ResultsViewerValues}」',其中ResultsViewerValues是視圖模型中的屬性(DataTable) – user3189858 2014-10-30 05:32:43