34

最好的解释方法是举例:

这是模型

public class Person 
{
    public int age;
    public string name;
}

这是视图模型

public class PersonVM
{    
}

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

4

4 回答 4

38

关于这个问题没有普遍的共识。例如,这是 Ward Bell在这里提出的关于 MVVM 的开放式问题之一:

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

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

  • 您可以将其用作“类固醇转换器”,以方便的方式为视图格式化模型值

  • 您可以注入与用户界面相关的其他功能,如数据验证消息撤消重做、..

缺点是:

  • 您将不得不复制大量代码以在视图模型中公开所有模型属性。

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

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

于 2009-07-14T16:29:05.670 回答
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;
    }
}

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

于 2009-07-11T20:36:48.647 回答
6

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

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

他使用动态视图模型在模型之上提供一个层,同时避免代理所有模型属性。

如果您的问题空间不需要高性能(动态确实会影响性能),那么这是一个很好的解决方案。View 不需要知道有关 Model 的任何信息,但 View Model 不必代理“按原样”提供的属性。可以随时将属性添加到 View Model 以包装 Model 属性,而无需修改 View 或 Model。阅读文章了解更多详情。

于 2011-01-05T14:52:39.243 回答
5

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

于 2010-04-18T13:52:22.810 回答