如何正确定义Model到ViewModel的关系?

我试图理解Model到ViewModel的关系,并且我一直在遇到同样的问题。 假设我们有一个只有一个字段的“Person”类:

public class Person { public string Name; } 

在下一阶段,我让我的XAML艺术家创建了一个呈现Person的用户控件,他根据MVVM的实践需要将他的视图与VMPerson(View-Model Person)联系起来,所以现在我添加另一个类:

 public class VMPerson : INotifyPropertyChange { private Person person; public VMPerson():this(new Person()){} public VMPerson(Person person) { this.person = person; } public Name { get { return person.name; } { set { person.name = value; PropertyChange("Name"); } } 

所以现在我几乎所有的设置..但我的VM类如何与我的模型类中的更改相关? 如果我添加INotifyPropertyChanged并在模型中为“Name”添加一个属性,我将使用与我的ViewModel类非常相似的内容添加一个我不需要的额外层。 有没有办法保持我的Model类不变,并且仍然会在view-model类中通知它内部的更改? 如果没有其他方法比使用INotifyPropertyChanged机制或类似的将在模型中实现的为什么我需要VM? 是否只是为了将一些“模型”类聚合到一个将被提供给View的类中的情况?

我认为我必须在我的理解中遗漏一些东西因为在我看来,根据我所描述的模型来查看模式,而使用View代码隐藏作为控制器将比MVVM更好的抽象,但我当然不确定。 有人可以向我解释我错过了什么吗? 谢谢。

将viewmodel代码放入模型中并不是最好的主意

确实,在许多情况下,视图模型通过看起来像额外的代码层来开始生活,这些代码层并没有真正添加任何有价值的东西,但重点是它们可以进化

VM的作用是为视图提供便利INotifyPropertyChanged就是这样一种便利,而模型的作用是封装您的业务逻辑 。 随着代码function的增长,意志越来越丰富; 在某些时候,它甚至可能最终在代码大小上比模型大得多。 因此,区别在于方便性和业务逻辑部分保持良好的分离,这对代码的可维护性有很好的影响。

将viewmodel代码放入视图中并不是最好的主意

这里的原因是不同的:如果你这样做,然后需要将viewmodel与另一种类型的视图一起使用,你必须将所有逻辑复制到另一个视图的代码隐藏中。 复制很糟糕; 干很好。

考虑到MVVM的一个非常重要的特性是它提供了可测试性,并且可测试性必然意味着至少两种类型的视图(真实的和模拟的),这种方法的必要性变得明显。

viewmodel的一个目的是从模型中获取数据,以必须可视化数据的方式处理它。

例如,在您的模型中,您可以获得DateOfBirth信息,并且您希望可视化实际年龄。

在这种情况下,您应该在ViewModel中进行处理(将DateOfBirth转换为实际年龄,如DateTime.Now.Year – DateOfBirth.Year)。

在您的特定情况下,ViewModel只是来自模型的数据的包装器(无处理),并且显然不需要Viewmodel。

为了在ViewModel中获取模型更改(对于不需要在VM中处理的属性),我通常也在模型中实现INotifyPropertyChanged。 这避免了ViewModel中的大量包装器属性。

在我的ViewModel中,我会有一些想法

 _model.PropertyChanged += PropertyChangedEventHandler(OnPropertyChangedModel); void OnPropertyChangedModel(object sender, System.ComponentModel.PropertyChangedEventArgs e) { OnPropertyChanged(e.PropertyName); } 

请注意,在这种情况下,模型属性将直接发送到View(ViewModel中没有处理)。

我看待它的方式如下: – ViewModel,这就像旧MVP中的Presenter一样,它将包含和连接各种业务function(如消耗IDealService和IStaticDataService)。

我的模型非常接近DataModel,它只是重复数据。

如果VM有太多与数据相关的位,我通常会将它们移动到Model中并使用VM中的实例。

即你可能有:

 public class VMPerson : INotifyPropertyChange { public Person PersonItem {get; set;} public VMPerson() { PersonItem = new Person(); } } 

你仍然可以在你的via中找到Person的名字: {Binding PersonItem.Name}

我同意如果你的origianl Person类不inheritanceINPC,那么很难让它成为通知。