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不更新

TreeView 数据绑定及选中命令处理

WPF使用HierarchicalDataTemplate绑定Dictionary生成TreeView

Treeview selectedItem 在启动时突出显示

TransferValue - 在 TreeView ItemsSource 中生成的隐式转换器 <null>

如何将 DataGridTemplateColumn.Visibility 绑定到 DataGrid.ItemsSource 之外的属性?