-4

(我使用 .Net 4.5 和 Visual Studio 2017。在帖子末尾添加了最小示例链接,如果您想自己查看这些内容,可以运行/崩溃而无需做任何事情)

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

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

最初,我正在做一个同步加载。一切运行良好(我正在加载很多东西,包括这些项目的列表)。但是我已经把加载放到了一个后台工作程序中(运行得几乎没有问题),后来,使用 Task.Run() 将后台工作程序替换为异步加载。

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

我尝试了很多东西,很多来自 myGrid.Dispatcher 的 BeginInvoke、App 的当前 Dispatcher 等等,以及我找到的每一段异步代码,但我不知道如何向这个 ObservableCollection 添加一个简单的项目。

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

我对我认为 UserControl_DataContextChanged 属于 UI 线程这一事实感到困惑,因此它应该能够安全地更改用户控件。

我在这里上传了一个“最小示例”=> https://files.fm/u/k2srba6m 问题出在 ItemViewmodel.FilterColumns 中,就像我的原始代码一样(希望这个解决方案也适用于原始代码)

任何帮助将不胜感激(对不起我的英语)

4

2 回答 2

0

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

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

对不起,再一次,没有引用完整的代码,只是“belletristic小说”,但它可能会有所帮助。

于 2017-10-18T19:41:28.117 回答
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 中找到另一种方法来做到这一点。

于 2017-10-18T09:36:58.987 回答