C# MVVM-属性在模型或视图模型中更改?

C# MVVM-属性在模型或视图模型中更改?,c#,mvvm,C#,Mvvm,我已经阅读了一些MVVM教程,我已经看到了这两种方法。大多数使用ViewModel进行PropertyChanged(这是我一直在做的),但我在模型中遇到了一个这样做的。这两种方法都可以接受吗?如果是这样,不同方法的优缺点是什么?根据经验,您将绑定到的任何对象(即使不需要双向绑定和属性更改通知)都必须实现INotifyPropertyChanged。这是因为如果不这样做,INotifyPropertyChanged应该由视图使用的所有类型实现(当然,除非它只有常量值) 是否将模型(不是viewm

我已经阅读了一些MVVM教程,我已经看到了这两种方法。大多数使用ViewModel进行PropertyChanged(这是我一直在做的),但我在模型中遇到了一个这样做的。这两种方法都可以接受吗?如果是这样,不同方法的优缺点是什么?

根据经验,您将绑定到的任何对象(即使不需要双向绑定和属性更改通知)都必须实现
INotifyPropertyChanged
。这是因为如果不这样做,INotifyPropertyChanged应该由视图使用的所有类型实现(当然,除非它只有常量值)


是否将模型(不是viewmodels)返回到视图?如果是,则应实现INotifyPropertyChanged

INotifyPropertyChanged(INPC)接口用于
绑定

因此,在一般情况下,您希望在
ViewModel
中实现它

视图模型
用于将
模型
视图
分离,因此您的
模型
中不需要使用INPC,因为您不希望
绑定到
模型

在大多数情况下,即使是较小的属性,您仍然有一个非常小的
ViewModel

如果您想为
MVVM
打下坚实的基础,您可能会使用类似的MVVM框架。使用它将为您提供一个
ViewModelBase
(或者这里是
NotifyPropertyChangedBase
),这样您就不必自己实现这些接口成员,只需使用
NotifyOfPropertyChange(()=>MyProperty)
,这更简单,更不容易出错

更新 因为似乎有很多Windows窗体开发人员,这里有一个很好的例子 这篇文章将加深对MVVM的理解:


我特别链接了问题涉及的数据模型部分。

微软的模式和实践,MVVM的发明者,我都不同意所选择的答案

通常,模型实现的功能使其易于绑定到视图。这通常意味着它通过INotifyPropertyChanged和INotifyCollectionChanged接口支持属性和集合更改通知。表示对象集合的模型类通常派生自ObservableCollection类,该类提供INotifyCollectionChanged接口的实现

--Microsoft模式和实践:

此时,数据绑定开始发挥作用。在简单的示例中,视图是直接绑定到模型的数据。模型的某些部分通过单向数据绑定简单地显示在视图中。通过直接将控件双向绑定到数据,可以编辑模型的其他部分。例如,模型中的布尔值可以是绑定到复选框的数据,也可以是绑定到文本框的字符串字段

--约翰·戈斯曼,MVVM的发明者:

我自己的文章:


一个“视图模型”只是包装一个模型并公开相同的属性列表,这是一种反模式。视图模型的工作是调用外部服务,并公开这些服务返回的单个模型和模型集合

原因:

  • 如果直接更新模型,视图模型将不知道触发属性更改事件。这会导致UI不同步
  • 这严重限制了在父视图模型和子视图模型之间发送消息的选项
  • 如果模型有自己的属性更改通知,#1和2不是问题。相反,如果包装器VM超出范围,但模型没有超出范围,则必须担心内存泄漏
  • 如果您的模型很复杂,有很多子对象,那么您必须遍历整个树,并创建第二个对象图来遮挡第一个对象图。这可能非常乏味,而且容易出错
  • 包装的集合尤其难以处理。任何时候(UI或后端)从集合中插入或删除项时,都需要更新卷影集合以匹配。这种代码很难正确编写
  • 这并不是说您永远不需要包装模型的视图模型。如果视图模型公开的属性与模型明显不同,并且不能用IValueConverter覆盖,那么包装视图模型是有意义的

    您可能需要包装视图模型的另一个原因是,由于某些原因,您的数据类不支持数据绑定。但即便如此,通常还是创建一个普通的、可绑定的模型并从原始数据类复制数据更好


    当然,您的视图模型将具有特定于UI的属性,例如当前选择了集合中的哪个项。

    完全同意Jonathan Allen的观点

    如果您没有什么要添加到“视图模型”(命令、影响表示的视图特定属性等)中,那么我肯定会在模型中实现INotifyPropertyChanged并直接公开它(如果可以,则“模型”可能不是您的)。你不仅会重复很多样板代码,而且让它们保持同步绝对是一件痛苦的事情


    INotifyPropertyChanged不是特定于视图的接口,它只执行名称所暗示的功能—在属性更改时引发事件。WinForms、WPF和Silverlight恰好支持它进行绑定——我肯定是出于非表示性目的使用它的

    虽然我通常支持实现INPC的模型,但在复合视图模型中调用INPC是因为它公开了可绑定到视图的推断属性。IMO由于INPC被烘焙到System.dll中,实现它的模型可能被认为是POCO。对于集合,基于模型的INPC具有性能优势。在64位平台上,包装器VM在