【问题标题】:In MVVM model should the model implement INotifyPropertyChanged interface?在 MVVM 模型中,模型是否应该实现 INotifyPropertyChanged 接口?
【发布时间】:2011-10-18 19:47:51
【问题描述】:

我对 MVVM 模式中的 View 和 ViewModel 有清晰的认识。我计划在我的应用程序中实现 MVVM 模式。我面临一个关于模型的问题。我有 .xml 文件被解析,信息显示在视图中。

我只需要第一次收到有关模型更改的通知。从按需开始,我需要得到通知。

那么如何实现模型呢?

我也应该在模型类中实现INotifyPropertyChanged 接口吗? (我读到该模型不应该实现 INotifyPropertyChanged 接口,因为它是 WPF 特定的)

【问题讨论】:

标签: .net wpf design-patterns mvvm inotifypropertychanged


【解决方案1】:

在模型中实现INotifyPropertyChanged 是完全可以接受的 -

通常情况下,模型实现的功能可以让您轻松 绑定到视图。这通常意味着它支持属性和 通过INotifyPropertyChanged 和 INotifyCollectionChanged 接口。模型类代表 对象的集合通常源自 ObservableCollection<T> 类,它提供了 INotifyCollectionChanged接口。

虽然由您决定是否需要这种类型的实现,但请记住 -

如果您的模型类没有实现所需的接口怎么办?

有时您需要使用不支持的模型对象 实现INotifyPropertyChanged、INotifyCollectionChanged、 IDataErrorInfo 或 INotifyDataErrorInfo 接口。在那些情况下, 视图模型可能需要包装模型对象并暴露 视图所需的属性。这些属性的值将 由模型对象直接提供。视图模型将 为它公开的属性实现所需的接口 视图可以轻松地将数据绑定到它们。

取自 - http://msdn.microsoft.com/en-us/library/gg405484(PandP.40).aspx

我在一些项目中工作过,但我们没有在我们的模型中实现INotifyPropertyChanged,因此我们遇到了很多问题;在 VM 中需要不必要的属性重复,同时我们必须在将底层对象(使用更新的值)传递给 BL/DL 之前更新它们。

如果您需要处理模型对象的集合(例如在可编辑的网格或列表中)或复杂模型,您将特别面临问题;模型对象不会自动更新,您必须在 VM 中管理所有这些。

【讨论】:

  • 看看polymod.codeplex.com。您可以将您的模型作为 POCO,用 Polymod 代理包装它,该代理为您提供 INotifyPropertyChanged 甚至 IDataErrorInfo 开箱即用。它在你的模型/视图模型中节省了大量的编码。
  • 如果你使用 DTO 会做什么;你会用 INotifyPropertyChanged 污染它吗?我尝试分享一些使用 Compact Framework 实现此功能的模型,但失败了
  • 这是我一直在寻找的答案。我有一个到处都在使用的模型,它有一个项目列表,当它们更改时,虚拟机不会更新。解决此问题的唯一方法是将 inotifypropertychanged 添加到模型中......或者将模型继承到视图模型中,但更愿意减少代码量......如果有其他方法,我很高兴听到关于它...
  • 我知道你在引用微软的话;然而,允许你的模型实现有一些严重的影响,特别是IDataErrorInfo。 IDataErrorInfo 背后的理念要求模型可以在某个时间点以无效状态存在,这会使模型类很容易变得贫血。另见Mark Seemann's Blog 和Martin Fowler's Article。
  • 是的,我并不是要恢复旧帖子,而是想确保过来的人知道IDataErrorInfo 的风险。我同意 INotifyPropertyChanged 在模型中应该很好(并且是首选) - 与 INotifyCollectionChanged 相同。我唯一的问题是IDataErrorInfo。从我的角度来看,此界面返回用户友好的错误消息(表示逻辑),这使其更适合视图模型。我很高兴看到您的经历证实了我的新发现。 :)
【解决方案2】:

标准的 MVVM 方法是仅在 ViewModel 上实现INotifyPropertyChanged。目的是在 ViewModel 发生变化时刷新 View 上的适当绑定。

但是,这针对View对 ViewModel 的更改。也就是说,当你改变一个TextBox中的值时,ViewModel上的INotifyPropertyChanged实现会刷新相关的Bindings,所以View会正确更新。

它不涵盖外部来源对模型所做的更改,例如数据库更改或其他接口。只要所有数据修改都来自 View,ViewModel 就应该知道所有更改并知道要更新什么。例如,如果您知道更改模型上的变量 Foo 也会更改模型上的 Bar 的值,那么当您更改值时,最好在 ViewModel 中同时调用 OnPropertyChanged(Foo) 和 OnPropertyChanged(Bar) Foo.

另一种选择是使用模型和视图模型之间的事件来刷新视图模型上需要更新的值。如果如您所说,“仅第一次”需要通知,那么在某些触发器上实施手动刷新一次也应该有效。

【讨论】:

  • 如果我的 ViewModel 中有模型的 ObservableCollection,并且我想更改这些对象怎么办?...然后我必须在这些模型上实现 INotifyPropertychanged,为此制作单独的层是没有意义的。
【解决方案3】:

这是使用 MVVM 时非常常见的问题,INotifyPropertyChanged 不是 WPF 特定的,因为它是 System.ComponentModel 的一部分,因此无需在您的解决方案中添加任何 WPF 特定参考。

如果您将在您的模型中实现INofityPropertyChanged,它可以在 ViewModel(代理属性)中节省更多代码。因此,您的模型使用INotifyPropertyChanged 是可以接受的。

【讨论】:

    【解决方案4】:

    有时让模型实现INotifyPropertyChanged 接口是可以接受的。

    例如,如果模型有很多要可视化的属性,并且您希望避免在视图模型中实现大量代码(代理属性)来公开这些模型属性。

    看http://msdn.microsoft.com/en-us/magazine/ff798279.aspx

    【讨论】:

      【解决方案5】:

      这是“纯”MVVM 编码员与其他人之间的经典争论。

      我倾向于尽可能阅读书籍,因为大多数时候这是有道理的。但在某些场景下,根据需要即兴编写代码,可以减少大量重复代码。

      在您的情况下,您可以将 XML 读取到模型类,然后将模型类复制到视图模型,或者将您想要的属性从模型复制到视图模型。这样您就可以控制更新 UI/模型。如果您遵循第一种方法,则需要在模型类中实现 Inotifypropertychanged,这是可以接受的。

      话虽如此,我会尽我所能遵循第二种方法,因为这将使我能够精确控制视图中显示/操作的所有属性。此外,我不会打破 MVVM 模式,我会感觉好多了。

      【讨论】:

        【解决方案6】:

        我不确定你的意思。在 VM 中,您可能有 INotifyPropertyChanged 或 DependencyProperty-es(在这种情况下,VM 必须派生自 DependencyObject)。两者兼有是没有意义的。没有它们也没有意义。

        在模型中,您可以为所欲为。触发/接收事件的能力很好,但并非总是可以依赖它们。基本上模型依赖于源数据和相关的东西,而视图模型则承担着模型与表示层的接口。由于 WPF 处理事件,至少VM 必须提供一些通知机制。

        【讨论】:

          猜你喜欢
          • 2015-01-20
          • 1970-01-01
          • 2011-07-14
          • 2010-10-20
          • 1970-01-01
          • 2014-09-30
          • 2018-09-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多