如何正确定义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,那么很难让它成为通知。