我们应该将视图绑定到模型属性还是ViewModel应该具有它自己的属性?


21

我正在使用以下技术环境启动一个项目:.Net 4.0,Entity Framework 4.0,带有MVVM体系结构的 WPF

我在网上看到了很多例子,有些书就是关于这种环境的。在某些示例中,作者有以下想法:

  1. Viemodel将具有Model类的实例(实体框架实体,例如Person)
  2. 将WPF视图控件绑定到Model的属性

虽然有些作者这样做:

  1. Viemodel将公开模型的所有属性。
  2. 将WPF视图控件绑定到ViewModel的属性,而不是直接绑定到模型。

那么,让视图绑定模型的属性而不是让视图模型公开自己的属性是一个好主意吗?还是更优选?


我个人发现公开模型的属性可以使数据层和逻辑层很好地分离。
Alex Hope O'Connor

Answers:


25

我认为许多程序员首先尝试采用直接绑定到模型的快捷方式,但是以我的经验,这样做有一些主要缺点。主要的问题是,如果您的实体模型由NHibernate或类似组织保留,那么只要View更新了模型属性,则NHibernate 可能人员保留这些更改保留到数据库中。对于具有“保存/取消”按钮的编辑屏幕,此方法效果不佳。实际上,它可能选择以批处理方式等待并保留所有内容,但其想法是,当您更改模型时,您将提交更改。

因此,您仍然可以避免直接绑定到只读屏幕上的模型属性,但是这样会出现不一致的情况。

此外,大多数模型都没有实现,INotifyPropertyChanged因此如果在初始显示后屏幕的状态发生变化,它们可能就不是合适的绑定目标。

鉴于自动属性的简便性,我建议始终将View绑定到ViewModel,而不是Model。它是一致,简单的,为您提供最大的灵活性以支持将来的更改。


我喜欢你的回答。+1代表“编辑/保存屏幕”。但是,两次写入属性(一次在模型中,一次在视图模型中)将是艰巨的。这也将增加开发时间。您认为这样做是合理的吗?
Pravin Patil

9
@Pravin Patil-过去,每当我采用该快捷方式时,我都会在以后不得不修复时诅咒自己。在ViewModel上重新实现属性的工作很少,尤其是如果它们是只读的(因为您可以将私有属性使用自动实现的属性)。实际上,在大多数情况下,模型是与ViewModel不同的数据结构。留给自己灵活性,可以在不影响视图的情况下更改模型。更改视图的次数越少越好,因为视图很难测试。
Scott Whitlock,

4
@Scott Whitlock:我已经使用NHibernate开发WPF应用程序两年了,从来没有遇到任何直接绑定到模型的麻烦。实际上,当模型属性发生更改时,无论绑定到什么内容,更改几乎都是相同的工作。而且,当我以后确实确实需要在ViewModel本身中完成一些路由时,那么在我需要之前花时间不值得。我遵循YAGNI(尚未)方法,没有任何困难。我认为您和此处的其他人对此问题有些教条。
猎鹰

16

a的要点ViewModel是它是的模型View

您应该将绑定ViewModelView,而不是任何Model属性(无论如何都不要直接绑定)。


8

我发现两种方法都可以接受

仅绑定到ViewModel的方法是“ MVVM-purist”方法,它可以使层之间更好地分离。绑定到模型通常更快,更方便。

除非我有充分的理由将各层完全分开(项目的大小,将来的维护问题,正在使用的模型的类型等),否则我将绑定到该模型。


7

我认为您所看到的是一个称为绑定通过的概念,也就是说,如果您的模型具有名为name的属性,并且您的视图模型无需进行任何其他编辑或转换即可公开此属性,那么您可以将其绑定到模型。

伪代码:

 {Binding: MyViewModel.MyModel.Name}

这样做是为了减少视图模型上的“绒毛”属性,但是从长远来看,这也是一个坏主意。视图模型的概念是确保视图不依赖于模型。通过绑定,您现在必须确保模型包含一个名为name的属性,否则您的实现将被破坏。

但是,如果仅绑定到视图模型,则可以更改模型,并且视图将永远不会知道,因为它只会在视图模型上看到名为Name的属性。

现在,在某些情况下,只要您的模型基于接口,就可以缓解这种情况。因此,如果接口具有公开属性ModuleName的IBaseDetails,则可以:

伪代码:

 {Binding: MyViewModel.MyModel.ModuleName}

只要您制作的任何模型都满足IBaseDetails接口,您就可以了,但是请注意,这是一个极端的情况,通常,将视图模型包裹在它涵盖的所有模型上通常总比90%更好。



1

我之所以来到这里,只是因为我有同样的疑问,并且我确信我将始终绑定到视图模型而不是模型。

采取角反应形式的方法。您可以使用“视图模型”中的一些信息来创建表单组,但是稍后您必须访问表单。值用于获取值并使用自动映射器或手动值将值复制到模型中。我认为没有什么比对视图模型中的属性出价更漂亮的事情了,例如,我有一个项目视图页面,其中有项目名称,客户名称等

项目与客户之间存在关系,因为项目有客户。因此,在此级别上,我不必关心那种关系,我只需要在视图中直观地显示项目名称和客户端名称,因此我在视图模型项目名称和客户端名称中放置了2个属性,因此我将视图控件绑定到两个稍后,我将担心在从模型具有的任何结构中获取代码后,为代码中的那些属性赋值。

在保存/取消的情况下,更新模型也可能是一样的。


这篇文章很难阅读(文字墙)。您介意将其编辑为更好的形状吗?
gna

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.