【发布时间】:2021-11-13 07:53:14
【问题描述】:
我创建了一个自定义 FrameWorkElement (Battery.cs) 以在 UI 中向用户表示数据。在 Battery.cs 类中,我有几个 dependencyProperties,因此 UI 可以监控各种更改并在更改时重新渲染对象。
我将 ObservableCollection 放在我的 MainWindowViewModel.cs 中,它通过 ListBox 绑定到主视图。
一切正常,但这仅用于测试,因为我需要将集合移至另一个将管理/更新电池的类。这种管理将异步发生,因此我在 Battery.cs 类中的 DependencyProperties 调用遇到了很多问题,因为它们是在 UI 线程上而不是在管理/进程线程上。
所以我删除了 DependencyProperties,并尝试将 DependencyProperty 向上移动到 MainWindowViewModel.cs。现在我没有收到关于哪个线程拥有所有权的错误,我可以看到 ObservableCollection 中的电池正在更新。但是,UI 永远不会调用 OnRender 方法。所以电池不再被渲染/显示。
这是 MainWindowViewModel.cs 中 DependencyProperty 的代码
public static readonly DependencyProperty batteriesProperty = DependencyProperty.Register(
"Batteries",
typeof(ObservableCollection<Battery>),
typeof(MainWindow),
new UIPropertyMetadata(new ObservableCollection<Battery>()));
public ObservableCollection<Battery> Batteries
{
get { return tbModel.Modules[0].batteries; }
}
我认为我的主要问题可能在这一行
new UIPropertyMetadata(new ObservableCollection<Battery>()));
但是我似乎无法弄清楚它应该是什么,或者如何调整代码,以便一旦我在 Battery.cs 类中调用 InvalidateVisual 后 UI 会更新图形。
public void UpdatePacket(Packet packet)
{
packet= packet;
Voltage = packet.Voltage;
InvalidateVisual();
}
InvalidateVisual() 方法正在执行,但 OnRender 覆盖从未被执行。
【问题讨论】:
-
对不起,我可能误解了你的解释。您是在写 BatteryProperty 是 ViewModel 的成员吗?因此,您将 ViewModel 传递给 FrameWorkElement 的 DataContext 属性?如果是这样,那么 ViewModel 不是可视树的一部分。因此,在 ViewModel 中调用 InvalidateVisual() 不会对可视化树产生任何影响,因此不会调用 OnRender() 方法。
-
没有在 FrameworkElement 类上调用 InvalidateVisual()。显示的依赖属性是写在 ViewModel 中的,所以我们没有线程冲突。当我在 Battery.cs 类中拥有依赖属性并在 ViewModel 中拥有 ObservableCollection 时,一切正常。然而,一旦我开始线程化并将 ObservableCollection 移动到我在模型中实际需要它的位置,就是我开始遇到问题的时候了。
标签: c# wpf data-binding observablecollection