MVVM:VM对象是应该直接暴露M对象,还是只通过getter委托给M的getter?

Che*_*rot 32 c# getter design-patterns access-modifiers mvvm

最好的解释方法是举例如下:

这是模型

public class Person 
{
    public int age;
    public string name;
}
Run Code Online (Sandbox Code Playgroud)

这是视图模型

public class PersonVM
{    
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:
vm应该将人员暴露给数据模板还是用他自己的属性封装模型属性?

Dan*_*iCE 36

关于这个问题没有普遍的一致意见.例如,这是Ward Bell 在这里提出的关于MVVM的一个开放性问题:

是否允许VM为V提供未包装的M对象(例如,原始Employee)?或者M-object的属性(如果它甚至被允许具有属性!)必须通过VM包装器的表面专门公开?

不直接在VM中公开Model的主要优点是:

  • 您可以将其用作"类固醇转换器",以便于视图的方式形成模型值

  • 你可以注入与用户界面相关的其他功能,比如数据验证消息,undo redo,..

缺点是:

  • 您将不得不复制大量代码以公开viewmodel中的所有模型属性.

  • 如果将视图控件绑定到viewmodels属性,则将从viewmodel发送propertyChanged事件.但是,如果模型属性从不同于viewmodel setter的其他源更改,会发生什么?然后它必须通知viewmodel所以你以2 OnPropertyChanged结束,一个在模型中,一个在viewmodel中......非常复杂!

所以对我来说,正确的答案是:这取决于你的要求.


jas*_*son 22

视图模型应声明其自己的属性,并从视图中隐藏模型的细节.这为您提供了最大的灵活性,并有助于防止模型类型问题泄漏到模型类中.通常,您的视图模型类通过委托来封装模型.例如,

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

请记住:模型不应该知道有关正在使用它的视图模型的任何信息,并且视图模型不应该知道有关正在使用它的视图的任何信息.视图应该对潜伏在后台的模型一无所知.因此,将模型封装在视图模型中的属性后面.

  • PersonViewModel类具有带PersonModel参数的公共构造函数.所以视图必须知道模型来实例化视图模型......它不是mvvm.构造函数应该是内部的,或者只采用字符串等通用参数来实现模型. (2认同)

Jos*_*h G 6

Robert McCarter在MSDN第25卷中提出了一个有趣的解决方案.

http://msdn.microsoft.com/en-us/magazine/ff798279.aspx

他使用动态视图模型在模型顶部提供图层,同时避免代理所有模型属性.

如果您的问题空间不需要高性能(动态性能会导致性能损失),这是一个很好的解决方案.View不需要了解有关模型的任何信息,但View Model不必"按原样"提供代理属性.在任何时候都可以将属性添加到视图模型中以包装模型属性,而无需修改视图或模型.阅读文章了解更多详情.


小智 5

拥有任何模型的ViewModel可能比这更糟糕.如果您有模型的层次结构,甚至是简单的集合,该怎么办?在这种情况下,您将必须遍历所有模型并为每个模型构建一个ViewModel实例,并且还要注册通知更改事件或其他事件.恕我直言,这完全是疯了,而且不合理.正如DaniCE所说,你最终会遇到很多代码并且头痛不已.

  • 我同意你的看法,现在怎么样? (2认同)
  • 如果您不将模型与View分开,为什么需要viemmodel?您最终可能会将Model设置为datacontext. (2认同)