最好的解释方法是举例:
这是模型
public class Person
{
public int age;
public string name;
}
这是视图模型
public class PersonVM
{
}
我的问题是:
vm应该将人员暴露给数据模板还是用他自己的属性封装模型属性?
答案 0 :(得分:36)
关于这个问题,我们没有达成一致意见。例如,这是由Ward Bell here制定的关于MVVM的一个开放性问题:
VM是否允许提供V an 展开的M对象(例如,原始的 员工)?或者必须是M-object的 属性(如果甚至允许的话 有财产!)暴露 完全通过表面的 VM包装器?
不直接在VM中公开Model的主要优点是:
您可以将其用作“类固醇转换器”,以便于查看方式形成模型值
您可以注入与用户界面相关的其他功能,例如data validation messages,undo redo,..
缺点是:
您必须复制大量代码才能在viewmodel中公开所有模型属性。
如果将视图控件绑定到viewmodels属性,则将从viewmodel发送propertyChanged事件。但是,如果模型属性从不同于viewmodel setter的其他源更改,会发生什么?然后它必须通知viewmodel所以你以2 OnPropertyChanged结束,一个在模型中,一个在viewmodel中......非常复杂!
所以对我来说,正确的答案是:这取决于你的要求。
答案 1 :(得分:21)
视图模型应声明自己的属性,并从视图中隐藏模型的细节。这为您提供了最大的灵活性,并有助于防止模型类型问题泄漏到模型类中。通常,您的视图模型类通过委托来封装模型。例如,
class PersonModel {
public string Name { get; set; }
}
class PersonViewModel {
private PersonModel Person { get; set;}
public string Name { get { return this.Person.Name; } }
public bool IsSelected { get; set; } // example of state exposed by view model
public PersonViewModel(PersonModel person) {
this.Person = person;
}
}
请记住:模型不应该知道有关使用它的视图模型的任何信息,并且视图模型不应该知道有关使用它的视图的任何信息。视图应该对潜伏在后台的模型一无所知。因此,将模型封装在视图模型中的属性后面。
答案 2 :(得分:6)
Robert McCarter在MSDN第25卷中提出了一个有趣的解决方案。
http://msdn.microsoft.com/en-us/magazine/ff798279.aspx
他使用动态视图模型在模型顶部提供图层,同时避免代理所有模型属性。
如果您的问题空间不需要高性能(动态性能会导致性能损失),这是一个很好的解决方案。 View不需要了解有关模型的任何信息,但View Model不必“按原样”提供代理属性。在任何时候都可以将属性添加到视图模型中以包装模型属性,而无需修改视图或模型。阅读文章了解更多详情。
答案 3 :(得分:5)
拥有任何模型的ViewModel可能比这更糟糕。如果您有模型的层次结构,甚至是简单的集合,该怎么办? 在这种情况下,您将必须遍历所有模型并为每个模型构建一个ViewModel实例,并且还要注册通知更改事件或其他事件。恕我直言,这完全是疯了,而且不合理。正如DaniCE所说,你最终会遇到很多代码而且头痛不已。