简体   繁体   English

MVVM:使用TreeViewItem中的IsExpanded和IsSelected扩展只读模型

[英]MVVM: Extending a Read-Only Model with IsExpanded and IsSelected in TreeViewItem

Consider a ViewModel that exposes a tree defined in the Model , which is then data-bound to a TreeView . 考虑一个ViewModel ,它公开了Model定义的树,然后树将其数据绑定到TreeView The tree is rather large and the model is used directly because it is essentially read-only with regards to the view. 该树很大,可以直接使用该模型,因为它在视图方面本质上是只读的。 Now, the TreeView lives under a TabControl in the VisualTree, so an issue at this point is that the IsExpanded and IsSelected properties aren't preserved when switching between tabs. 现在, TreeView TabControl在VisualTree的TabControl下,因此,此时的问题是在选项卡之间切换时未保留IsExpandedIsSelected属性。 One hesitates to add these boolean properties to each node in the Model , as this should be extended in the ViewModel as a matter of principle. 有人犹豫将这些布尔属性添加到Model每个节点,因为原则上应该在ViewModel对其进行扩展。 The tree is composed of polymorphic nodes, so if we were to create a ViewModel node type that derives from the tree node types and adds these properties, it seems this would result in some hairy code in the ViewModel : 该树由多态节点组成,因此,如果我们要创建一个从树节点类型派生并添加这些属性的ViewModel节点类型,看来这会在ViewModel产生一些冗长的代码:

That is, if the tree has an abstract NodeBase , and then derived types Node1 , Node1 , ... NodeN (the Model 's Node s). 也就是说,如果树具有抽象的NodeBase ,然后派生类型Node1Node1 ,... NodeNModelNode )。 The ViewModel then has to encapsulate these nodes, so when creating a ViewModelNode , if it has a reference to Node and also references to child ViewModelNode 's for each descendent ViewModelNode that encapsulates each descendent Model 's Node all the way down the tree, maintaining these child references in the ViewModel identically to how they are maintained in the Model , along with a reference to the Model . 然后, ViewModel必须封装这些节点,因此在创建ViewModelNode ,如果它具有对Node的引用,并且还对每个后代ViewModelNodeViewModelNode都具有引用,则该子孙ViewModelNode将每个后代Model的Node封装在树上,并保持ViewModel中的这些子引用与它们在Model中的维护方式相同,并带有对Model的引用。 ie all references in the Model nodes are replicated in the ViewModel nodes, in order for each Model node to be encapsulated by a ViewModel node. 即,将Model节点中的所有引用复制到ViewModel节点中,以使每个Model节点都由ViewModel节点封装。 The existence of redundant references such as this, even if handled in the ViewModelNode 's constructor, just smells bad. 即使在ViewModelNode的构造函数中进行处理,这种冗余引用的存在也很难闻。

What is the most accepted means to extend each node in a tree in this scenario, without wholesale replication of the references as stated above? 在这种情况下,没有如上所述的引用的批量复制,扩展树中每个节点的最可接受的方法是什么? (And to a lesser point, is the mere mention of using the model directly by the view an unforgivable crime, or is this forgiven due to the circumstances?) (在较小程度上,仅出于观点而提及直接使用该模型是不可原谅的犯罪,还是由于情况而被宽恕?)

There is perhaps an argument to be made that implementing those Boolean properties on the Model is OK, but personally I would look to creating ViewModels for each Model that's going to be in the TreeView . 可能会有一个论点,那就是在Model上实现这些布尔属性是可以的,但是我个人希望为TreeView中的每个Model创建ViewModels。 One advantage of doing so would perhaps be an increase in scalability, should you ever decide to implement more functionality related to the TreeView . 如果您决定实现与TreeView相关的更多功能,那么这样做的好处之一可能是可伸缩性的提高。

I think it depends on how much you are actually doing with the TreeView (within your app), but I do think the more you're doing, the stronger the argument for a ViewModel-based solution. 我认为这取决于您实际上对TreeView (在您的应用程序内)执行的操作,但是我确实认为您所做的越多,基于ViewModel的解决方案的论据就越强大。

With regards to the hairy code, you could perhaps circumvent this to a degree by using an interface to describe your TreeView members, eg: 关于冗长的代码,您可以通过使用描述您的TreeView成员的interface来在某种程度上规避它,例如:

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

    // Further potential properties

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

This approach can be used to ensure that your TreeView members are properly "subscribed". 此方法可用于确保正确“订阅”您的TreeView成员。 There's also then an option to reference the interface type in XAML, for example, as the TargetType of a HierarchicalDataTemplate for the TreeView . 然后还有一个选项来引用XAML中的interface类型,例如,作为TreeViewHierarchicalDataTemplateTargetType

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM