从WPF中的任何线程修改Datagrid.Columns

时间:2017-10-18 08:15:20

标签: c# wpf datagrid async-await cross-thread

(我使用.Net 4.5,使用Visual Studio 2017.在帖子的末尾添加了最小的示例链接,并准备好运行/崩溃,如果你想看到自己的事情,没有任何事情可做)< / p>

我有一个在WPF中包含DataGrid的UserControl。它绑定到一个Viewmodel,它包含一个DataTable和一个自定义的列列表,以便在我现在无法立即删除它们时隐藏它们中的一些。

DataGrid.Columns是readonly,所以在UserControl.DataContextChanged(我在下面解释原因)中,我得到了新的DataContext,清除了我的grid.Columns集合并用我在加载时读取的DataGridColums的自定义列表提供它

最初,我正在进行同步加载。一切都运行正常(我正在加载很多东西,包括这些项目的列表)。但我已经将加载放入后台工作程序(运行得非常好),然后使用Task.Run()通过异步加载替换后台工作程序。

我窗口中所有其他项目列表都已正确加载,代码运行正常。但是当我试图用其他的替换mygrid.Columns时,我有一个InvalidOperationException,说调用线程无法访问这个对象,因为另一个线程拥有它。

我尝试了很多东西,很多来自myGrid.Dispatcher的BeginInvoke,App的当前Dispatcher等等,以及我发现的每一段异步代码,但我无法弄清楚如何向这个ObservableCollection添加一个简单的项目。

我见过自定义asyncObservableCollection但不能使用它们,DataGrid.Columns是只读的。

我很困惑的事实是我认为UserControl_DataContextChanged属于UI线程,因此它应该能够安全地更改用户控件。

我在这里更新了一个“最小例子”=&gt; https://files.fm/u/k2srba6m 问题在于ItemViewmodel.FilterColumns,正如我的原始代码所做的那样(希望解决方案也适用于原始代码)

任何帮助都会受到赞赏(对不起我的英语)

2 个答案:

答案 0 :(得分:0)

如果您使用 .Net 4.5 或更高版本,可以尝试使用BindingOperations.EnableCollectionSynchronization

在你的窗口构造函数中:

// Sync collection with UI
BindingOperations.CollectionRegistering += BindingOperations_CollectionRegistering;

并添加此方法:

/// <summary>
/// Handles the CollectionRegistering event of the BindingOperations control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="CollectionRegisteringEventArgs"/> instance containing the event data.</param>
private void BindingOperations_CollectionRegistering(object sender, CollectionRegisteringEventArgs e)
{
    BindingOperations.EnableCollectionSynchronization(e.Collection, e.Collection);
}

只要创建了ObservableCollection,这将自动调用EnableCollectionSynchronization方法。

我把它设置为简单地使用集合本身作为lockObject,不知道这是不是一个坏主意,但它在我的最终工作。

如果您使用的是 .Net 4.0 ,则可能必须让AsyncObservableCollection正常工作。我还没有在.Net 4.0中找到另一种方法。

答案 1 :(得分:0)

感谢另一个论坛的帮助,我找到了答案。 我在这里留下问题,因为答案很难找到。

添加到DataGrid.Columns在viewmodel中手动实例化的DataGridColumn是错误的,应该在UI线程中调用instanciation本身。 OC.Add引发了异常但主要是因为参数(在某些情况下是调用本身,是的)。

很抱歉,再一次,没有充满代码的引号,只是“belletristic小说”,但它可能有所帮助。