C# WPF MVVM动态列多线程
我目前正在开发一个C#System.Windows.Controls.DataGrid,它需要根据数据动态生成列。它可以在运行时添加和/或删除列 我在ViewModel类中使用一个线程来更新提供给DataGrid的ObservableCollection 我读过这本书,它解释了我为我的问题找到的最佳解决方案。尽管如此,DataGridExtension类中的Columns.CollectionChanged委托引发InvalideOperationException:调用线程无法访问此对象,因为其他线程拥有它 这里有一些代码来描述这一切:C# WPF MVVM动态列多线程,c#,wpf,mvvm,datagrid,dynamic-columns,C#,Wpf,Mvvm,Datagrid,Dynamic Columns,我目前正在开发一个C#System.Windows.Controls.DataGrid,它需要根据数据动态生成列。它可以在运行时添加和/或删除列 我在ViewModel类中使用一个线程来更新提供给DataGrid的ObservableCollection 我读过这本书,它解释了我为我的问题找到的最佳解决方案。尽管如此,DataGridExtension类中的Columns.CollectionChanged委托引发InvalideOperationException:调用线程无法访问此对象,因为
视图XAML
<DataGrid ItemsSource="{Binding CollectionView, Source={StaticResource ViewModel}}" local:DataGridExtension.Columns="{Binding DataGridColumns, Source={StaticResource ViewModel}}" AutoGenerateColumns="False" Name="dataGrid">
public static class DataGridExtension
{
public static Dispatcher _currentDispatcher;
public static readonly DependencyProperty ColumnsProperty =
DependencyProperty.RegisterAttached("Columns",
typeof(ObservableCollection<DataGridColumn>),
typeof(DataGridExtension),
new UIPropertyMetadata(new ObservableCollection<DataGridColumn>(), OnDataGridColumnsPropertyChanged));
private static void OnDataGridColumnsPropertyChanged(DependencyObject iObj, DependencyPropertyChangedEventArgs iArgs)
{
if (iObj.GetType() == typeof(DataGrid))
{
DataGrid myGrid = iObj as DataGrid;
ObservableCollection<DataGridColumn> Columns = (ObservableCollection<DataGridColumn>)iArgs.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)
{
UserControl control = ((UserControl)((Grid)myGrid.Parent).Parent);
foreach (DataGridColumn column in args.NewItems.Cast<DataGridColumn>())
{
/// This is where I tried to fix the exception. ///
DataGridColumn temp = new DataGridTextColumn();
temp.Header = column.Header;
temp.SortMemberPath = column.SortMemberPath;
control.Dispatcher.Invoke(new Action(delegate()
{
myGrid.Columns.Add(temp);
}), DispatcherPriority.Normal);
////////////////////////////////////////////////////
}
}
if (args.OldItems != null)
{
foreach (DataGridColumn column in args.OldItems.Cast<DataGridColumn>())
{
myGrid.Columns.Remove(column);
}
}
};
}
}
}
public static ObservableCollection<DataGridColumn> GetColumns(DependencyObject iObj)
{
return (ObservableCollection<DataGridColumn>)iObj.GetValue(ColumnsProperty);
}
public static void SetColumns(DependencyObject iObj, ObservableCollection<DataGridColumn> iColumns)
{
iObj.SetValue(ColumnsProperty, iColumns);
}
}
UserControl control = ((UserControl)((Grid)myGrid.Parent).Parent);
Columns.CollectionChanged += delegate(object sender, NotifyCollectionChangedEventArgs args)
{
control.Dispatcher.Invoke(new Action(delegate()
{
if (args.NewItems != null)
{
foreach (DataGridColumn column in args.NewItems.Cast<DataGridColumn>())
{
DataGridColumn temp = new DataGridTextColumn();
temp.Header = column.Header;
temp.SortMemberPath = column.SortMemberPath;
myGrid.Columns.Add(temp);
}
}
if (args.OldItems != null)
{
foreach (DataGridColumn column in args.OldItems.Cast<DataGridColumn>())
{
myGrid.Columns.Remove(column);
}
}
}), DispatcherPriority.Normal);
};
视图模型类
public ObservableCollection<DataGridColumn> DataGridColumns
{
get { return columns; }
set { columns = value; }
}
private void getViewData()
{
while (true)
{
Thread.Sleep(1000);
foreach (DataObject data in dataObjects)
{
int index = -1;
foreach (DataGridColumn c in columns)
{
if (c.Header.Equals(column.Header))
index = columns.IndexOf(c);
}
DataGridColumn column = new DataGridTextColumn();
... Creating the column based on data from DataObject ...
DataGridExtension._currentDispatcher = Dispatcher.CurrentDispatcher;
if (index == -1)
{
this.columns.Add(column);
}
else
{
this.columns.RemoveAt(index);
this.columns.Add(column);
}
}
}
}
公共ObservableCollection DataGridColumns
{
获取{返回列;}
设置{columns=value;}
}
私有void getViewData()
{
while(true)
{
睡眠(1000);
foreach(数据对象中的数据对象数据)
{
int指数=-1;
foreach(列中的DataGridC列)
{
if(c.标题等于(列标题))
索引=列。IndexOf(c);
}
DataGridColumn=新DataGridTextColumn();
…根据来自DataObject的数据创建列。。。
DataGridExtension.\u currentDispatcher=Dispatcher.currentDispatcher;
如果(索引==-1)
{
this.columns.Add(column);
}
其他的
{
this.columns.RemoveAt(索引);
this.columns.Add(column);
}
}
}
}
DataGridExtension类
<DataGrid ItemsSource="{Binding CollectionView, Source={StaticResource ViewModel}}" local:DataGridExtension.Columns="{Binding DataGridColumns, Source={StaticResource ViewModel}}" AutoGenerateColumns="False" Name="dataGrid">
public static class DataGridExtension
{
public static Dispatcher _currentDispatcher;
public static readonly DependencyProperty ColumnsProperty =
DependencyProperty.RegisterAttached("Columns",
typeof(ObservableCollection<DataGridColumn>),
typeof(DataGridExtension),
new UIPropertyMetadata(new ObservableCollection<DataGridColumn>(), OnDataGridColumnsPropertyChanged));
private static void OnDataGridColumnsPropertyChanged(DependencyObject iObj, DependencyPropertyChangedEventArgs iArgs)
{
if (iObj.GetType() == typeof(DataGrid))
{
DataGrid myGrid = iObj as DataGrid;
ObservableCollection<DataGridColumn> Columns = (ObservableCollection<DataGridColumn>)iArgs.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)
{
UserControl control = ((UserControl)((Grid)myGrid.Parent).Parent);
foreach (DataGridColumn column in args.NewItems.Cast<DataGridColumn>())
{
/// This is where I tried to fix the exception. ///
DataGridColumn temp = new DataGridTextColumn();
temp.Header = column.Header;
temp.SortMemberPath = column.SortMemberPath;
control.Dispatcher.Invoke(new Action(delegate()
{
myGrid.Columns.Add(temp);
}), DispatcherPriority.Normal);
////////////////////////////////////////////////////
}
}
if (args.OldItems != null)
{
foreach (DataGridColumn column in args.OldItems.Cast<DataGridColumn>())
{
myGrid.Columns.Remove(column);
}
}
};
}
}
}
public static ObservableCollection<DataGridColumn> GetColumns(DependencyObject iObj)
{
return (ObservableCollection<DataGridColumn>)iObj.GetValue(ColumnsProperty);
}
public static void SetColumns(DependencyObject iObj, ObservableCollection<DataGridColumn> iColumns)
{
iObj.SetValue(ColumnsProperty, iColumns);
}
}
UserControl control = ((UserControl)((Grid)myGrid.Parent).Parent);
Columns.CollectionChanged += delegate(object sender, NotifyCollectionChangedEventArgs args)
{
control.Dispatcher.Invoke(new Action(delegate()
{
if (args.NewItems != null)
{
foreach (DataGridColumn column in args.NewItems.Cast<DataGridColumn>())
{
DataGridColumn temp = new DataGridTextColumn();
temp.Header = column.Header;
temp.SortMemberPath = column.SortMemberPath;
myGrid.Columns.Add(temp);
}
}
if (args.OldItems != null)
{
foreach (DataGridColumn column in args.OldItems.Cast<DataGridColumn>())
{
myGrid.Columns.Remove(column);
}
}
}), DispatcherPriority.Normal);
};
公共静态类DataGridExtension
{
公共静态调度器\u currentDispatcher;
公共静态只读依赖项属性列属性=
DependencyProperty.RegisterAttached(“列”,
类型(可观测采集),
类型(DataGridExtension),
新的UIPropertyMetadata(新的ObservableCollection(),OnDataGridColumnsPropertyChanged));
私有静态无效OnDataGridColumnsPropertyChanged(DependencyObject iObj,DependencyPropertyChangedEventArgs)
{
if(iObj.GetType()==typeof(DataGrid))
{
DataGrid myGrid=iObj作为DataGrid;
ObservableCollection列=(ObservableCollection)iArgs.NewValue;
if(列!=null)
{
myGrid.Columns.Clear();
if(Columns!=null&&Columns.Count>0)
{
foreach(DataGridColumn DataGridColumn in Columns)
{
myGrid.Columns.Add(dataGridColumn);
}
}
Columns.CollectionChanged+=委托(对象发送方,NotifyCollectionChangedEventArgs args)
{
如果(args.NewItems!=null)
{
UserControl=((UserControl)((Grid)myGrid.Parent.Parent);
foreach(args.NewItems.Cast()中的DataGridColumn列)
{
///这就是我试图修复异常的地方///
DataGridColumn temp=新DataGridTextColumn();
临时标题=列标题;
temp.SortMemberPath=column.SortMemberPath;
control.Dispatcher.Invoke(新操作(委托)()
{
myGrid.Columns.Add(临时);
}),DispatcherPriority.Normal);
////////////////////////////////////////////////////
}
}
如果(args.OldItems!=null)
{
foreach(args.OldItems.Cast()中的DataGridColumn列)
{
myGrid.Columns.Remove(column);
}
}
};
}
}
}
公共静态ObservableCollection GetColumns(DependencyObject iObj)
{
返回(ObservableCollection)iObj.GetValue(ColumnsProperty);
}
公共静态void集合列(DependencyObject iObj、ObservableCollection iColumns)
{
iObj.SetValue(ColumnsProperty,iColumns);
}
}
我放置的部分///这是我试图修复异常的部分。///就是抛出异常的地方,正好在myGrid.add(…)
myGrid对象不允许我将该列添加到DataGrid的列集合中。这就是我用Dispatcher.Invoke包围它的原因。奇怪的是,如果我执行myGrid.Columns.Add(newDataGridTextColumn());它可以工作,我可以在视图中看到添加的空列,但是myGrid.columns.Add(temp);抛出异常
这东西一定有什么我不懂的。请帮忙 编辑以下Stipo建议
<DataGrid ItemsSource="{Binding CollectionView, Source={StaticResource ViewModel}}" local:DataGridExtension.Columns="{Binding DataGridColumns, Source={StaticResource ViewModel}}" AutoGenerateColumns="False" Name="dataGrid">
public static class DataGridExtension
{
public static Dispatcher _currentDispatcher;
public static readonly DependencyProperty ColumnsProperty =
DependencyProperty.RegisterAttached("Columns",
typeof(ObservableCollection<DataGridColumn>),
typeof(DataGridExtension),
new UIPropertyMetadata(new ObservableCollection<DataGridColumn>(), OnDataGridColumnsPropertyChanged));
private static void OnDataGridColumnsPropertyChanged(DependencyObject iObj, DependencyPropertyChangedEventArgs iArgs)
{
if (iObj.GetType() == typeof(DataGrid))
{
DataGrid myGrid = iObj as DataGrid;
ObservableCollection<DataGridColumn> Columns = (ObservableCollection<DataGridColumn>)iArgs.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)
{
UserControl control = ((UserControl)((Grid)myGrid.Parent).Parent);
foreach (DataGridColumn column in args.NewItems.Cast<DataGridColumn>())
{
/// This is where I tried to fix the exception. ///
DataGridColumn temp = new DataGridTextColumn();
temp.Header = column.Header;
temp.SortMemberPath = column.SortMemberPath;
control.Dispatcher.Invoke(new Action(delegate()
{
myGrid.Columns.Add(temp);
}), DispatcherPriority.Normal);
////////////////////////////////////////////////////
}
}
if (args.OldItems != null)
{
foreach (DataGridColumn column in args.OldItems.Cast<DataGridColumn>())
{
myGrid.Columns.Remove(column);
}
}
};
}
}
}
public static ObservableCollection<DataGridColumn> GetColumns(DependencyObject iObj)
{
return (ObservableCollection<DataGridColumn>)iObj.GetValue(ColumnsProperty);
}
public static void SetColumns(DependencyObject iObj, ObservableCollection<DataGridColumn> iColumns)
{
iObj.SetValue(ColumnsProperty, iColumns);
}
}
UserControl control = ((UserControl)((Grid)myGrid.Parent).Parent);
Columns.CollectionChanged += delegate(object sender, NotifyCollectionChangedEventArgs args)
{
control.Dispatcher.Invoke(new Action(delegate()
{
if (args.NewItems != null)
{
foreach (DataGridColumn column in args.NewItems.Cast<DataGridColumn>())
{
DataGridColumn temp = new DataGridTextColumn();
temp.Header = column.Header;
temp.SortMemberPath = column.SortMemberPath;
myGrid.Columns.Add(temp);
}
}
if (args.OldItems != null)
{
foreach (DataGridColumn column in args.OldItems.Cast<DataGridColumn>())
{
myGrid.Columns.Remove(column);
}
}
}), DispatcherPriority.Normal);
};
UserControl=((UserControl)((Grid)myGrid.Parent.Parent);
Columns.CollectionChanged+=委托(对象发送方,NotifyCollectionChangedEventArgs args)
{
control.Dispatcher.Invoke(新操作(委托)()
{
如果(args.NewItems!=null)
{
foreach(args.NewItems.Cast()中的DataGridColumn列)
{
DataGridColumn temp=新DataGridTextColumn();
临时标题=列标题;
temp.SortMemberPath=column.SortMemberPath;
myGrid.Columns.Add(临时);
}
}
如果(args.OldItems!=null)
{
foreach(args.OldItems.Cast()中的DataGridColumn列)
{
myGrid.Columns.Remove(column);
}
}
}),DispatcherPriority.Normal);
};
WPF扩展(可在codeplex中找到)有一个名为DispatchedObservableCollection
的ObservableCollection扩展版本,在这里非常理想。值得一看并进行相应的定制。WPF Extension(可在codeplex中找到)有一个名为DispatchedObservableCollection的扩展版本,在这里非常理想。值得一看并进行相应的定制。将DataGridColumn创建代码移到dispatcher委托中
发生此问题的原因是DataGridColum