如何在ViewModel中公开Model的集合

5

我正在为代表递归嵌套类型的类实现MVVM。例如:

class NestedType
{
    // Other properties here

    public Collection<NestedType> SubElements {get; set;}
}

class NestedTypeViewModel
{
    ObservableCollection<NestedType> ModelCollection { ??? }
}

我该如何以可观察的方式公开 Model 集合中的项目呢?(例如,View 将添加、创建和修改子元素)我假设我需要 ViewModel 中的集合是 ObservableCollection<T>,但 Model 中需要什么呢?我也可以将其作为 ObservableCollection 并直接公开它... 有什么建议吗?

除非在属性上调用了PropertyChanged,否则不应该有setter。对于集合,通常通过提供私有后备字段和公共getter来使其readonly - H.B.
2个回答

2
你可以直接从你的模型中返回ObservableList。WPF将获取集合的引用并注册到模型集合的CollectionChanged事件中。
class MyViewModel
{
  public ObservableCollection<NestedType> MyItems { return Model.Items; }
} 

但是,使用MVVM会破坏您尝试实现的内容。ViewModel不应该公开模型,单个或集合,否则您的视图可能会绑定到模型,在MVVM中不应该这样做。

好吧,MVVM并不是一种宗教,每个人都以不同的方式实现某些部分。如果这对您来说没有问题...那么请直接进行操作。

如果您想要一个干净的解决方案,您有多种选择。只需允许管理器修改模型的集合并创建相应的视图模型,或者我的最爱方法是拥有一个对象来同步模型和视图模型集合,并自动将新添加的模型包装在一个新的视图模型中,然后将此vm添加到父视图模型列表中。


4
与您的评论相反,认为公开模型以进行数据绑定会“破坏”MVVM,微软在定义Model类时已经记录:“模型类通常通过INotifyPropertyChanged和INotifyCollectionChanged接口提供属性和集合更改通知事件。这使得它们可以轻松地在视图中进行数据绑定。代表对象集合的模型类通常派生自ObservableCollection<T>类。” - RMart
1
@RMart +1 因为那是关于MVVM的很好的参考资料。 - Brian Triplett
这就是为什么我说“每个人实现某些部分的方式都不同”,没有对错之分。在我看来,最好将所有内容都包装在一个视图模型中,而不是直接将模型绑定到视图上。例如,如果有一个模型列表,但你需要在每个项目上执行一个命令,那么该命令应该是模型的视图模型属性,而不是直接在模型中定义。但是,只要你定义了规则、约束和目标,你可以按照自己的需求和喜好来实现MVVM。 :) - dowhilefor

0
只要您不需要将不同的“Model”传递到“ViewModel”中,就可以不使用单独的“Model”实体而生存。因此,您可以坚持使用代表实际“Model”数据的“ViewModel”。
我建议在幕后使用私有字段公开它,并使用“INotifyPropertyChanged”。
class NestedTypeViewModel 
{     
    private ObservableCollection<NestedType> dataItems; 

    public ObservableCollection<NestedType> DataItems
    {
       get
       { 
          return this.dataItems;
       }
       private set
       {
           this.dataItems = value;
           // here is should be OnPropertyChanged("DataItems") call
       }
    } 
} 

编辑:回复评论

但是如果您已经有了像Model这样的实体-请尝试通过接口将其注入ViewModel中,以便至少使Model和ViewModel解耦。


非常感谢您的回答,但不幸的是,在这种情况下我确实需要一个单独的虚拟机,原因有几个。1)该虚拟机具有一堆ICommands(未显示),以支持与视图的交互(上面的示例是简化的,以说明问题的重点)。2)该模型在我们公司的其他项目中也被使用,我不能修改它以适应我的VM需求。 - Brian Triplett
我的意思是你不需要一个单独的MODEL,但如果你已经有这样的实体 - 那么尝试通过接口将其注入到ViewModel中,这样Model和ViewModel至少会解耦。 - sll

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接