MVVM:在TreeViewItem中扩展具有IsExpanded和IsSelected的只读模型

时间:2017-12-01 14:25:30

标签: c# wpf mvvm data-binding

考虑ViewModel公开Model中定义的树,然后将数据绑定到TreeView。树相当大,模型直接使用,因为它对视图基本上是只读的。现在,TreeView位于VisualTree中的TabControl下,因此此时出现的问题是在切换选项卡时不会保留IsExpandedIsSelected属性。有人不愿意将这些布尔属性添加到Model中的每个节点,因为这应该在ViewModel中作为原则扩展。树由多态节点组成,因此如果我们要创建一个从树节点类型派生的ViewModel节点类型并添加这些属性,那么这似乎会导致ViewModel中的一些毛茸茸的代码:

即,如果树具有抽象NodeBase,然后是派生类型Node1Node1,... NodeNModel' s Node s)。然后ViewModel必须封装这些节点,因此在创建ViewModelNode时,如果它有Node的引用,并且每个后代都引用了子ViewModelNode { {1}}将每个后代ViewModelNode的Node一直封装在树下,将Model中的这些子引用与ViewModel中维护它们的方式保持一致,同时对Model的引用。即,Model节点中的所有引用都在Model节点中复制,以便ViewModel节点封装每个Model节点。这样的冗余引用的存在,即使在ViewModel的构造函数中处理,也只是闻起来很糟糕。

在这种情况下,最常用的方法是在树中扩展每个节点,而不是如上所述批量复制引用? (在较小的一点上,仅仅提到直接使用模型是不可原谅的犯罪,或者由于情况而被原谅了吗?)

1 个答案:

答案 0 :(得分:0)

可能有一个论点要求在模型上实现这些布尔属性是正常的,但我个人希望为TreeView中的每个模型创建ViewModel。如果您决定实现与TreeView相关的更多功能,那么这样做的一个优点可能是可扩展性的提高。

我认为这取决于你在TreeView(在你的应用程序中)实际做了多少,但我认为你做的越多,基于ViewModel的解决方案的论据就越强

关于毛茸茸的代码,您可以使用interface来描述您的TreeView成员,从而在一定程度上避开这种情况,例如:

public interface IMyTreeViewItem
{
    bool TreeViewItemIsSelected { get; set; }
    bool TreeViewItemIsExpanded { get; set; }

    // Further potential properties

    string TreeViewItemHeaderText { get; set; }
    List<IMyTreeViewItem> TreeViewItemChildren { get; set; }
}

此方法可用于确保您的TreeView成员正确&#34;订阅&#34;。然后还可以选择在XAML中引用interface类型,例如,TargetTypeHierarchicalDataTemplate的{​​{1}}。