gpt4 book ai didi

c# - 为什么在重新创建 WPF DataGrid 列时 Dispatcher.BeginInvoke 不起作用?

转载 作者:行者123 更新时间:2023-12-01 18:50:07 25 4
gpt4 key购买 nike

我有一个DataGrid为一系列日期动态生成一组列,并使用自定义依赖属性绑定(bind)到网格,

public static readonly DependencyProperty BindableColumnsProperty =
DependencyProperty.RegisterAttached("BindableColumns",
typeof(ObservableCollection<DataGridColumn>),
typeof(DataGridAttachedProperties),
new UIPropertyMetadata(null, BindableColumnsPropertyChanged));

BindableColumnsPropertyChanged包含以下代码,这就是问题发生的地方:

else if (ne.Action == NotifyCollectionChangedAction.Add)
{
foreach (DataGridColumn column in ne.NewItems)
{
dataGrid.Columns.Add(column);
}
}
else if (ne.Action == NotifyCollectionChangedAction.Remove)
{
foreach (DataGridColumn column in ne.OldItems)
{
dataGrid.Columns.Remove(column);
}
}

当我调用我的InitColumns时方法来自 RefreshCommand代码,dataGrid.Columns.Remove(column)我收到错误:

The calling thread cannot access this object because a different thread owns it. I fixed that by changing the Remove code to:

Application.Current.Dispatcher.BeginInvoke((Action)(() =>
{
dataGrid.Columns.Remove(column);
}));

然后我再试一次,Remove代码有效,但我显然在 dataGrid.Columns.Add(column) 上遇到了同样的错误线。我也改变了这一点:

Application.Current.Dispatcher.BeginInvoke((Action)(() =>
{
dataGrid.Columns.Add(column);
}));

我尝试再次运行刷新命令,再次调度新的 Remove仍然有效,但现在我遇到了同样的错误,但是使用 BeginInvoke代表dataGrid.Columns.Add(column)调用:

enter image description here

这个我不懂。它肯定是成功删除该列的同一个线程,但现在看起来像是某个新的幻像线程正在尝试添加该列。什么可能导致此情况?

最佳答案

据我了解,您正在操纵 UI 绑定(bind) ObservableCollection<DataGridColumn>来自非 UI 线程。所以使用Dispatcher处理时CollectionChanged (以及 PropertyChanged )并将更改应用到 DataGrid是正确的方法。

但是为什么Remove作品和Add不是吗?

帖子中没有显示,但我怀疑您不仅添加了 DataGridColumn您的可观察集合的后代,但您也在非 UI 线程上创建(并初始化)它们,这将导致所描述的行为。

这是因为 DataGridColumn 类继承(通过 DependencyObject ) DispatcherObject DispatcherObject类(因此是派生类)存储当前线程 Dispatcher在其构造函数中,然后使用该调度程序来验证每个依赖属性访问是从创建该对象的线程完成的。

不久,整个DataGridColumn创建和操作应该发生在 UI 线程上。使用 Application.Current.Dispatcher 找到创建列的代码并确保它在 UI 线程上执行。和一些 Dispatcher.Invoke过载。

附注虽然上面是我能想到的最合乎逻辑的解释,但是您可以通过修改发布的代码来验证假设是否正确,如下所示:

Application.Current.Dispatcher.BeginInvoke((Action)(() =>
{
if (!column.CheckAccess())
{
// Houston, we've got a problem!
}
dataGrid.Columns.Add(column);
}));

并在if内放置一个断点声明。

关于c# - 为什么在重新创建 WPF DataGrid 列时 Dispatcher.BeginInvoke 不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41075374/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com