MVVM中ViewModel中复制Model属性的问题

11

看起来有一个指导方针,即模型不应该将其实体暴露给视图(View),而所有必需的属性都应在ViewModel中复制。

示例:

Product
Id {get; set;}
Name {get; set;}
.......


ProductViewModel : ViewModelBase
Id {get; set;}
Name {get; set;}
.......
为什么需要这个?如果Model没有实现INPC我可以理解,但是如果它已经实现了,那我觉得这个步骤非常不必要。
4个回答

8
当视图绑定到模型时:
  • 如果视图需要更改或您有多个视图,则对模型的更改将导致所有绑定到该模型的视图发生更改。

  • 从视图的角度来看,它绑定的对象可能并不那么直观;当您需要向对象添加属性和/或命令时,您是将其添加到ViewModel并保留“原始”属性在Model中还是修改Model?

拥有ViewModel可以在单个Model和多个(版本的)View之间提供额外的抽象。

总之,这只是一个指导方针,但请注意,今天看起来很好的东西,在需要修改/更新应用程序时可能并不那么棒。


我认为模型是由外部来源提供的任何东西(代理类、存储库、流)。只有当我希望视图根据绑定到它的内容的更改而更新时,才需要使用INPC。出于我在答案中提到的原因,我从不将模型绑定到视图,这就是ViewModel的作用。 - Emond
嗨Erno,抱歉回复晚了,我在度假。你的第一点很有力。对于第二点的答案是:是的。如果我可以问一下:如果您只需要客户的简短信息,例如代码、名称和ID,您会使用仅包含这三个属性的CustomerBasicInfoViewModel,使用具有所有属性的完整Customer对象作为DTO,还是您也会在Model中保留CustomerBasicInfo以节省内存? - Goran
一如既往:这取决于情况。在 WPF(桌面应用程序)中,我不会担心几个(千)字节的内存,但我会首先关注带宽。大多数情况下,带宽决定对象的大小。 - Emond

5
指导只是指导,具体情况而定。纯粹主义者会认为完全将模型与视图分离可以使模型在不改变视图的情况下进行更改。
我倾向于仅在必要时(无论是INPC还是某些视图特定逻辑,例如模型具有FirstName和LastName但没有FullName)代理模型属性。
否则,我绑定到模型(ViewModel上的公共属性)。如果我的情况发生变化并且我需要封装某些内容,则在有需求时进行重构。
我始终尝试确保存在ViewModel(即使它仅公开模型),以便以后更容易进行重构。

嗨,亚当,抱歉回复晚了,我在度假。那么,如果您需要在发票视图上显示客户集合,只需要基本信息(例如代码、名称和ID),您会如何处理这种情况?您会在模型中拥有一个CustomerBasicInfo,还是...? - Goran
通常,模型由您的领域、Web服务等所决定。因此,您需要创建一个视图模型来包装模型,并使数据在视图中更易于呈现(例如,添加选中、可见等属性)。如果您有一个只读视图,而且您的模型与视图结构足够相似,则现在始终可以使用它,并在规格更改时将其替换为视图模型。但要注意不要让UI问题侵入您的模型中。 - Adam Mills

2
我的问题是,为什么你的模型要实现INPC?它们需要吗?
通常模型只是数据传输对象,并不需要任何更改逻辑。
另外,如果你的基本INPC实现来自MVVM框架,但你的模型存在于一个共享组件中,那么该组件是否需要引用你的MVVM框架,以及其他WPF组件呢?
我们遇到的情况是一组共享对象代表我们的数据在服务器和客户端上。客户端是一个WPF应用程序,所以没问题,但对于服务器端是一个服务,因此我们不需要INPC。

嗨,卡梅伦,抱歉回复晚了,我在度假。好吧,必须有人实现INPC,无论是客户(模型)还是CustomerViewModel。在每种情况下都需要DTO吗?如果您想从模型引入对MVVM框架的引用,则可以这样做,但不是必需的。INPC实现非常简单。 MVVM框架中的ViewModelBase仍将用作ViewModel的基础。我的问题是:如果我问“我应该在VM中复制所有模型属性”,答案是肯定的,无论应用程序类型如何,我想知道-为什么? - Goran

0

您的ViewModel不正确。 如果您已经有了一个Product类型的Model,您可以在ViewModel中简单地定义如下内容: public Product Product {...}


3
这是他问题的核心!将模型暴露给视图会绕过ViewModel的责任。 - Emond

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接