是否有可能在mvvm模式中获取wpf datagrid上的动态列?

我正在开发wpf(mvvm模式)的产品。 我有一个场景,我花了一个多星期没有好结果。 如果可以,请帮助我…这是场景,根据用户的自定义(用户ll选择列)我必须在datagrid中显示一组数据。 目前我正在将具有一组属性的ObservableCollection绑定到datagrid的itemsource。 这限制了我固定的列大小。 注意:列出了n个列名称供用户选择。 如果通过“datagrid.columns.add()”轻松完成后面的代码。 在这种情况下,任何人都可以帮助我。

我的xaml:

 

我的命令类:

 public static class DataGridExtension { public static ObservableCollection GetColumns(DependencyObject obj) { return (ObservableCollection)obj.GetValue(ColumnsProperty); } public static void SetColumns(DependencyObject obj, ObservableCollection value) { obj.SetValue(ColumnsProperty, value); } public static readonly DependencyProperty ColumnsProperty = DependencyProperty.RegisterAttached("Columns", typeof(ObservableCollection),typeof(DataGridExtension), new UIPropertyMetadata (new ObservableCollection(), OnDataGridColumnsPropertyChanged)); private static void OnDataGridColumnsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d.GetType() == typeof(DataGrid)) { DataGrid myGrid = d as DataGrid; ObservableCollection Columns = (ObservableCollection)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()) //{ // myGrid.Columns.Add(column); //} } if (args.OldItems != null) { //foreach (DataGridColumn column in args.OldItems.Cast()) //{ // myGrid.Columns.Remove(column); //} } }; } } } } 

和我在viewmodel中的属性:

 private ObservableCollection _columnCollection = new ObservableCollection(); public ObservableCollection ColumnCollection { get { return this._columnCollection; } set { _columnCollection = value; base.OnPropertyChanged("ColumnCollection"); //Error //base.OnPropertyChanged<ObservableCollection>(() => this.ColumnCollection); } } 

谢谢你的努力…最后我找到了解决方案….

这里.. ..(完整的wpf mvvm)

在我的命令文件中:

 public class DataGridColumnsBehavior { public static readonly DependencyProperty BindableColumnsProperty = DependencyProperty.RegisterAttached("BindableColumns", typeof(ObservableCollection), typeof(DataGridColumnsBehavior), new UIPropertyMetadata(null, BindableColumnsPropertyChanged)); private static void BindableColumnsPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) { DataGrid dataGrid = source as DataGrid; ObservableCollection columns = e.NewValue as ObservableCollection; dataGrid.Columns.Clear(); if (columns == null) { return; } foreach (DataGridColumn column in columns) { dataGrid.Columns.Add(column); } columns.CollectionChanged += (sender, e2) => { NotifyCollectionChangedEventArgs ne = e2 as NotifyCollectionChangedEventArgs; if (ne.Action == NotifyCollectionChangedAction.Reset) { dataGrid.Columns.Clear(); if (ne.NewItems != null) { foreach (DataGridColumn column in ne.NewItems) { dataGrid.Columns.Add(column); } } } else if (ne.Action == NotifyCollectionChangedAction.Add) { if (ne.NewItems != null) { foreach (DataGridColumn column in ne.NewItems) { dataGrid.Columns.Add(column); } } } else if (ne.Action == NotifyCollectionChangedAction.Move) { dataGrid.Columns.Move(ne.OldStartingIndex, ne.NewStartingIndex); } else if (ne.Action == NotifyCollectionChangedAction.Remove) { if (ne.OldItems != null) { foreach (DataGridColumn column in ne.OldItems) { dataGrid.Columns.Remove(column); } } } else if (ne.Action == NotifyCollectionChangedAction.Replace) { dataGrid.Columns[ne.NewStartingIndex] = ne.NewItems[0] as DataGridColumn; } }; } public static void SetBindableColumns(DependencyObject element, ObservableCollection value) { element.SetValue(BindableColumnsProperty, value); } public static ObservableCollection GetBindableColumns(DependencyObject element) { return (ObservableCollection)element.GetValue(BindableColumnsProperty); } } 

在我的xaml中:

  

最后在我的viewmodel中:

 private ObservableCollection _columnCollection = new ObservableCollection(); public ObservableCollection ColumnCollection { get { return this._columnCollection; } set { _columnCollection = value; base.OnPropertyChanged("ColumnCollection"); //Error //base.OnPropertyChanged>(() => this.ColumnCollection); } } private DataTable _datatable = new DataTable(); public DataTable Datatable { get { return _datatable; } set { if (_datatable != value) { _datatable = value; } base.OnPropertyChanged("Datatable"); } } 

在我的构造函数中:

 public MainViewModel() { Datatable.Columns.Add("Name",typeof(string)); Datatable.Columns.Add("Color", typeof(string)); Datatable.Columns.Add("Phone", typeof(string)); Datatable.Rows.Add("Vinoth", "#00FF00", "456345654"); Datatable.Rows.Add("lkjasdgl", "Blue", "45654"); Datatable.Rows.Add("Vinoth", "#FF0000", "456456"); System.Windows.Data.Binding bindings = new System.Windows.Data.Binding("Name"); System.Windows.Data.Binding bindings1 = new System.Windows.Data.Binding("Phone"); System.Windows.Data.Binding bindings2 = new System.Windows.Data.Binding("Color"); DataGridTextColumn s = new DataGridTextColumn(); s.Header = "Name"; s.Binding = bindings; DataGridTextColumn s1 = new DataGridTextColumn(); s1.Header = "Phone"; s1.Binding = bindings1; DataGridTextColumn s2 = new DataGridTextColumn(); s2.Header = "Color"; s2.Binding = bindings2; FrameworkElementFactory textblock = new FrameworkElementFactory(typeof(TextBlock)); textblock.Name = "text"; System.Windows.Data.Binding prodID = new System.Windows.Data.Binding("Name"); System.Windows.Data.Binding color = new System.Windows.Data.Binding("Color"); textblock.SetBinding(TextBlock.TextProperty, prodID); textblock.SetValue(TextBlock.TextWrappingProperty, TextWrapping.Wrap); //textblock.SetValue(TextBlock.BackgroundProperty, color); textblock.SetValue(TextBlock.NameProperty, "textblock"); //FrameworkElementFactory border = new FrameworkElementFactory(typeof(Border)); //border.SetValue(Border.NameProperty, "border"); //border.AppendChild(textblock); DataTrigger t = new DataTrigger(); t.Binding = new System.Windows.Data.Binding { Path = new PropertyPath("Name"), Converter = new EnableConverter(), ConverterParameter ="Phone" }; t.Value = 1; t.Setters.Add(new Setter(TextBlock.BackgroundProperty, Brushes.LightGreen, textblock.Name)); t.Setters.Add(new Setter(TextBlock.ToolTipProperty, bindings, textblock.Name)); DataTrigger t1 = new DataTrigger(); t1.Binding = new System.Windows.Data.Binding { Path = new PropertyPath("Name"), Converter = new EnableConverter(), ConverterParameter = "Phone" }; t1.Value = 2; t1.Setters.Add(new Setter(TextBlock.BackgroundProperty, Brushes.LightYellow, textblock.Name)); t1.Setters.Add(new Setter(TextBlock.ToolTipProperty, bindings, textblock.Name)); DataTemplate d = new DataTemplate(); d.VisualTree = textblock; d.Triggers.Add(t); d.Triggers.Add(t1); DataGridTemplateColumn s3 = new DataGridTemplateColumn(); s3.Header = "Name 1"; s3.CellTemplate = d; s3.Width = 140; ColumnCollection.Add(s); ColumnCollection.Add(s1); ColumnCollection.Add(s2); ColumnCollection.Add(s3); } 

我想扩展前面的例子(回答)订阅和取消订阅事件CollectionChanged的能力。

行为 (在System.Windows.Interactivity上添加引用):

  public class ColumnsBindingBehaviour : Behavior { public ObservableCollection Columns { get { return (ObservableCollection) base.GetValue(ColumnsProperty); } set { base.SetValue(ColumnsProperty, value); } } public static readonly DependencyProperty ColumnsProperty = DependencyProperty.Register("Columns", typeof(ObservableCollection), typeof(ColumnsBindingBehaviour), new PropertyMetadata(OnDataGridColumnsPropertyChanged)); private static void OnDataGridColumnsPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) { var context = source as ColumnsBindingBehaviour; var oldItems = e.OldValue as ObservableCollection; if (oldItems != null) { foreach (var one in oldItems) context._datagridColumns.Remove(one); oldItems.CollectionChanged -= context.collectionChanged; } var newItems = e.NewValue as ObservableCollection; if (newItems != null) { foreach (var one in newItems) context._datagridColumns.Add(one); newItems.CollectionChanged += context.collectionChanged; } } private ObservableCollection _datagridColumns; protected override void OnAttached() { base.OnAttached(); this._datagridColumns = AssociatedObject.Columns; } private void collectionChanged(object sender, NotifyCollectionChangedEventArgs e) { switch (e.Action) { case NotifyCollectionChangedAction.Add: if (e.NewItems != null) foreach (DataGridColumn one in e.NewItems) _datagridColumns.Add(one); break; case NotifyCollectionChangedAction.Remove: if (e.OldItems != null) foreach (DataGridColumn one in e.OldItems) _datagridColumns.Remove(one); break; case NotifyCollectionChangedAction.Move: _datagridColumns.Move(e.OldStartingIndex, e.NewStartingIndex); break; case NotifyCollectionChangedAction.Reset: _datagridColumns.Clear(); if (e.NewItems != null) foreach (DataGridColumn one in e.NewItems) _datagridColumns.Add(one); break; } } } 

查看

            

视图模型:

  private ObservableCollection _dataGridColumns; public ObservableCollection DataGridColumns { get { if (_dataGridColumns == null) _dataGridColumns = new ObservableCollection() { new DataGridTextColumn() { Header = "Column1" } }; return _dataGridColumns; } set { _dataGridColumns = value; OnPropertyChanged("DataGridColumns"); } }