[英]WPF TreeView: bindings not updating when TreeView is virtualizing
在我的 WPF 应用程序中,我有一个包含很多元素的 TreeView,所以我打开虚拟化来加速渲染,如下所示:
<TreeView VirtualizingPanel.IsVirtualizing="True">
...
</TreeView>
但是,如果我这样做,似乎数据绑定到我的 Viewm Model 中的属性的树项中的控件停止对OnPropertyChanged
事件做出反应。
例如,假设我的项目有以下模板:
<DataTemplate DataType="{x:Type viewModels:MyViewModel}">
<TextBlock Text="{Binding ItemName}" />
</DataTemplate>
model 是这样的:
public class MyViewModel: INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
private string itemName;
public string ItemName {
get { return itemName; }
set {
if(value != itemName) {
itemName = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ItemName)));
}
}
}
}
属性的初始绑定工作正常并且项目名称显示在 TextBlock 中,但是如果在呈现树视图项目后ItemName
属性的值发生更改,它将不会在 UI 中更新,就好像PropertyChanged
事件是被完全忽略。
我怎样才能解决这个问题? 请注意,如果我设置VirtualizingPanel.IsVirtualizing="False"
问题就会消失,所以这肯定是由虚拟化引起的。
经过进一步的测试和调试,我发现了这个问题,它与面板虚拟化没有严格的关系,我想那只是错误表现出来的一种情况。
基本上,在我的完整代码中(为简洁起见,我省略了) ItemName
属性是从Event Handler
内部设置的。 问题是我的处理程序是由代码中其他地方的后台线程中引发的事件触发的,因此它没有在 UI 线程上运行。 我的印象是这不是问题,因为我没有在 model 中操作任何 UI 对象(我只是触摸了我的 ViewModel 对象),但是显然如果你不在 UI 线程中提升PropertyChanged
变得不可靠.
为了解决这个问题,我在调度程序调用中将代码包装在我的处理程序中,如下所示:
private void MyEvenHandler(object sender, MyEventArgs e)
{
Dispatcher.Invoke(() =>
{
var myViewModel = FindVm(e);
myViewModel.ItemName = "updated";
}
}
现在一切都按预期工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.