gpt4 book ai didi

c# - 在 MVVM 中绑定(bind)时出现 WPF 线程绑定(bind)访问错误

转载 作者:行者123 更新时间:2023-12-03 10:26:43 25 4
gpt4 key购买 nike

因此,我正在尝试将 WPF 的动态数据显示合并到我的 MVVM caliburn 项目中(如果有人希望测试此错误,我正在使用来自动态数据显示的 future 的 LineChart 控件)。有一个 LineChart 绑定(bind)到 ObservableCollection。它仅在集合是在具有 LineChart 的控件的代码中进行时才有效。如果您尝试将 ViewModel 绑定(bind)到集合,则依赖属性会引发 InvalidOperationException。如何解决这个问题?

我已经看到当您更改属性绑定(bind)到的集合并知道修复该问题的方法时会发生这种情况,但在实际的绑定(bind)过程中从未发生过。我已经尝试将集合的创建放在调度程序调用中(就像您使用添加或删除一样),但它没有帮助。

编辑:正如我在第二段中所说,异常(exception)不是在更改集合的时候。它在绑定(bind)点被提升。更重要的是,我尝试使用 other question 中的解决方案他们没有帮助。

编辑#2:异常消息是“调用线程无法访问此对象,因为不同的线程拥有它”。
人们不断告诉我收集更改的解决方案,但它甚至没有涉及到更改。它在绑定(bind)阶段失败(xaml 中的 ItemsSource="{binding collection}")。

编辑#3:我仔细检查并注意到 ViewModel 是在 UI 线程中创建的,它只会提出更多问题。

最佳答案

好的,我花了很长时间才找到问题的根本原因。

与其他人所怀疑的不同,这根本不是多线程问题。
而是 DynamicDataDisplay 的问题。您正在使用的库。

您的 ItemsSource 有一个明确的原因绑定(bind)在您的 ListBox 上工作对象并且不适用于 Chart (类型 Microsoft.Research.DynamicDataDisplay.Markers2.LineChart ):Chart既没有视觉也没有逻辑父。

如果您将以下代码插入到 Button_Click 中,您可以检查这一点并在它们之后设置断点:

var visualParent = VisualTreeHelper.GetParent(Chart);
var logicalParent1 = Chart.Parent;
var logicalParent2 = LogicalTreeHelper.GetParent(Chart);

可以看到都是 null .
所以 Binding您在 LineChart.ItemsSourceProperty 上设置的与 Path=ExampleCollection找不到任何源值,只分配 nullItemsSource .那是因为 DataContext是从父级继承的 - 但是当没有任何父级时,就没有任何 DataContext继承任何一个。
因为 Chart不是视觉或逻辑树的一部分,没有(简单的)方法可以绑定(bind)到外部 DataContext甚至可以工作。

验证 DataContextnull只需将此行添加到前面的代码中:
var dataContext = Chart.DataContext;

现在有三种可能的解决方案。
第一 ,可以手动继承 DataContext来自 Window使用以下代码:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// Just add the following line.
Chart.DataContext = DataContext;

Chart.StrokeThickness = 3;
Chart.SetBinding(LineChart.ItemsSourceProperty, new Binding("ExampleCollection"));
// ...
}

如果您简单地添加这一行,您将看到您的其他多线程代码运行良好,并且图表已更新为某种正弦波模式。

第二 ,作为另一种可能的解决方案,您可以查阅 DynamicDataDisplay 的文档库并检查分配 ItemsSource 的正确和预期方式到 LineChart使用数据绑定(bind)。
我尝试自己搜索文档,甚至从该库中调试了两个小时左右的大量代码,但文档几乎不存在,而且代码太复杂,无法在几个小时内完全理解。我尝试使用几种工具(Visual Studio Live Visual Tree、Snoop、...)来显示 ChartPlotter 的可视化树。但我得到了 StackOverflowException每次,所以本质上这个库中的某些东西是有缺陷和错误的。

第三 ,您可以使用 Resource作为一种代理对象来创建到 MainWindowViewModel 的同一实例的“绑定(bind)桥” .
为此,您必须执行此处建议的操作: Data binding outside the visual tree. Data Context bridging

底线 : 所以,如果你只是想完成工作,我会设置 DataContext在如上所示的代码中。 (特别是如果 ViewModel 中的 DataContext 的实例从未改变。)
如果您想使用纯数据绑定(bind),那么我可能会使用“绑定(bind)桥”或搜索支持此方案的另一个图表库。

关于c# - 在 MVVM 中绑定(bind)时出现 WPF 线程绑定(bind)访问错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40590835/

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