TreeView ItemSsource 绑定到 ViewModel 不更新 xaml 控件项
Posted
技术标签:
【中文标题】TreeView ItemSsource 绑定到 ViewModel 不更新 xaml 控件项【英文标题】:TreeView ItemSource binding to ViewModel not updating xaml control's Items 【发布时间】:2021-11-22 17:55:40 【问题描述】:我正在创建一个包装 TreeView 元素的 UserControl(我们称之为 ViewTree)。在 ViewTree.xaml.cs 我有一个 Source
依赖属性:
public static readonly DependencyProperty SourceProperty
= DependencyProperty.Register (
"Source",
typeof (ObservableCollection<TreeItem>),
typeof (ViewTree),
new FrameworkPropertyMetadata (new ObservableCollection<TreeItem>(), OnSourceChanged)
);
public ObservableCollection<TreeItem> Source
get return (ObservableCollection<TreeItem>)GetValue(SourceProperty);
set SetValue(SourceProperty, value);
...这样 UserControl 的使用者可以进行输入绑定:
<features:ViewTree Source="Binding Path=...">
然而,在 ViewTree UserControl 中,我并不想直接绑定到这个 DependencyProperty。相反,我想绑定到 ViewModel 中的另一个属性(使用 Prism),所以我在 ViewTree.xaml.cs 中执行了此操作:
private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
var nextTreeSource = e.NewValue as ObservableCollection<TreeItem>;
if (nextTreeSource == null)
return;
var viewTree = d as ViewTree;
viewTree.UpdateTreeSource(nextTreeSource);
public void UpdateTreeSource(ObservableCollection<TreeItem> treeSource)
var vm = trvMenu.DataContext as ViewTreeViewModel;
vm.TreeSource = treeSource;
在我的 ViewTree.xaml 中,我有以下内容,并且树节点正常显示:
<TreeView Name="trvMenu" ItemsSource="Binding Path=TreeSource">
但是,当我尝试访问 ViewTree.xaml.cs 中的 trvMenu.Items
时,它显示为空。我在viewTree.UpdateTreeSource(nextTreeSource);
后面放了一个断点,可以验证viewTree.trvMenu.Items
里面有孩子。
如果我直接绑定到 DependencyProperty,它可以正常工作,但我仍然更喜欢 ViewModel 绑定。
如果有人能指出我做错了什么,或者这只是 WPF 的工作方式,我将不胜感激?
提前致谢。
【问题讨论】:
"with Prism"的意思是你依赖Prism来为你创建用户控件的视图模型? 是的,我的 xaml 中有prism:ViewModelLocator.AutoWireViewModel="True"
,并在初始化期间使用 ViewModel 类注册 UserControl 的映射。
目前还不清楚 UpdateTreeSource 应该做什么。它不会更改 Source 属性的绑定。相反,它会更改 DataContext 中的一个属性。这看起来很奇怪。
UpdateTreeSource
故意更改上下文 ViewTree 用户控件的 VM,我想将其用于绑定。 Source
DP 只是消费者和 UC 的输入桥。无论如何,DP和VM绑定没有错,只是设计中的一个错误。对不起,谢谢大家。
这不是您设计控件的方式。您希望允许您的控件与不同的视图模型类或数据上下文一起使用。您不会使用“视图模型”在内部备份您的控件。您添加包含此控件的逻辑和属性的代码隐藏文件或类。您必须将 TreeView 直接绑定到 Source 属性(或手动分配)。不要在内部使用“视图模型”。如果您的控件将直接链接到数据源,例如直接从数据库中读取,那么视图模型将是有意义的。但通常控件是被动显示数据而不是管理它
【参考方案1】:
经过一点调试,我发现了问题,完全是我的错,与DP或VM绑定无关。
我有 2 个 ViewTree 控件的使用者。在 ViewTree 中,我订阅了一个事件,当它触发时,两个 ViewTree 元素都会调用处理程序。
在未初始化 TreeSource 的消费者 ViewTree 上引发了异常。
【讨论】:
以上是关于TreeView ItemSsource 绑定到 ViewModel 不更新 xaml 控件项的主要内容,如果未能解决你的问题,请参考以下文章
MVVM Light,TreeView ItemSsource不更新
WPF使用HierarchicalDataTemplate绑定Dictionary生成TreeView
Treeview selectedItem 在启动时突出显示
TransferValue - 在 TreeView ItemsSource 中生成的隐式转换器 <null>
如何将 DataGridTemplateColumn.Visibility 绑定到 DataGrid.ItemsSource 之外的属性?