【问题标题】:MVVM: does change notification muddy the separation between model and viewmodel?MVVM:更改通知是否混淆了模型和视图模型之间的分离?
【发布时间】:2011-06-03 09:44:47
【问题描述】:

假设我有一个模型,它公开了我将在 GUI 中显示和更改的对象集合。

所以我们让 Model 暴露了 ModelItem 的集合。

View 绑定到 ViewModel,该 ViewModel 公开 ViewModelItem 的 ObservableCollection。 ViewModelItem 是 ModelItem 的 Viewmodel

View 包含一个 ListBox 和一个 DataTemplate。 DataTemplate 用于 ViewModelItem 类型的项目。 View DataContext 指向 ViewModel 的一个实例。 ListBox 绑定到 ObservableCollection。

我控制所有代码。

到目前为止很简单。问题:

是否可以将模型上的集合公开为 ObservableCollection?此外,在 Model 和 ModelItem 上实现 INotifyPropertyChanged 是否可以接受?

我担心我混淆了模型和视图模型之间的分离,但是常识说,这是一种通知模型中元素更改的机制,让我们使用它...

只是想从别人那里得到一些看法。

谢谢

【问题讨论】:

  • 您想让用户从视图内部操作您的数据还是只想显示它?
  • 我个人的经验是,MVVM一定不能推得太远。保持务实,否则你会过度设计整个事情。
  • 对不起,是的,数据可以通过视图进行编辑。

标签: wpf mvvm


【解决方案1】:

如果数据模型需要更改通知,在数据模型中使用更改通知当然是可以接受的。仅仅因为 UI 需要更改通知而在数据模型中使用更改通知也是有问题的。

通常,我将数据模型设计为没有 UI,并将视图模型用作抽象层,将数据模型的实现细节从 UI 中隐藏起来。另一方面,在动态应用程序中,更改通知的需求可能非常普遍,因此将其放入数据模型中更有意义。

【讨论】:

  • 其实这个和DanDan的回答很有意思。我没有提供很多细节,因为我在接受一般指导,但我认为我在暗示视图的工作是管理模型的表示和更新。编辑:哎呀命中返回。所以在这种情况下,底层模型和视图之间存在密切关系。我反对 DanDan,如果我的模型实现了一个提供 Observerable 集合的接口,那么任何实现该接口的模型都可以互换。这只是一个例子,而不是硬性规定。
  • 我正在开发的一个应用程序有一个非常动态的数据模型,它的设计完全支持 UI。在这种情况下,我将更改通知放入模型中没有问题,因为向 UI 提供信息是模型的主要目的。在这种情况下,我对模型设计的指导不是“如果 UI 不存在,我会以不同的方式设计吗?”但是“如果 UI 是 WinForms,我会以不同的方式设计吗?”
【解决方案2】:

没有。这太糟糕了。您的模型不应该知道它是如何使用的。给它这个知识会打败 MVVM 的对象。
该模型不应该知道它被 WPF、winforms、dos 控制台、作为服务或作为库使用。如果你告诉它,你就错了。 它也应该是独立于框架的,不介意它是 MVVM、MVC 还是 MXXX 的一部分!

【讨论】:

  • 我完全不同意,因为将这些元素添加到数据模型中既实用又正常,它们不是特定于 UI 的,甚至也不是 UI RELATED 结构。
【解决方案3】:

简答: 是的。当您需要通知更改时,请使用模型上的通知界面。不要担心用这个混淆你的代码。务实。

长答案: 我的理念是这样的:在实现 MVVM 时,直接绑定到模型对象,而无需额外操作。当您需要一些新的东西(新行为、视图将使用的属性等)时,您可以将模型对象包装在 ViewModel 对象中。除了从模型中委托数据之外什么都不做的 ViewModel 只不过是额外的代码。当您需要对模型对象提供给您的数据进行处理时,您需要引入层。

因此,为了进一步扩展我的想法(并更直接地回答您的问题),模型需要有一种方法可以在发生变化时告诉 ViewModel。通常,模型数据是不可变的,因此它不需要这种通知机制,因此没有必要。但是,模型也经常发生变化。发生这种情况时,模型有两个选择:使用自定义通知方法(事件、委托等)或使用INotifyPropertyChanged

如果您查看INotifyPropertyChanged 的命名空间,它在System.ComponentModel 中——不是视图——所以我更喜欢在模型中使用它。这是一个众所周知的接口,您可以使用它从您的视图直接绑定到您的模型。无需实现任何不同。

将这一理念更进一步,ObservableCollection 位于System.Collections.ObjectModel 中——也不是特定于视图的——它实现了System.Collections.Specialized.INotifyCollectionChanged,它也不是特定于视图的。换句话说,ObservableCollection 被设计成一个通知其观察者变化的集合。如果您有一个模型需要这样做,那么ObservableCollection 就是您的工具。 WPF 和 Silverlight 使用这些接口进行数据绑定只是很方便(但并非偶然)。

我想这是一种冗长的说法:“是的。当你需要通知更改时,请在模型上使用通知接口。不要担心用这个混淆你的代码。要务实。”

【讨论】:

    【解决方案4】:

    两者都做绝对是可以接受的。我什至会说两者都是必需。你的常识能力工作得很好。 :)

    我只想补充一点,如果您不需要 ModelItems 的所有 MVVM 功能,那么您可以通过暴露 ObservableCollection<ModelItem> 而不是 ObservableCollection<ViewModelItem> 并修改您的 DataTemplate 来偷工减料适合。这将为您节省相当多的“准备”代码,因此请权衡利弊。

    【讨论】:

    • 很高兴知道。我不确定是什么导致了这种不安感,我想我期待一些事情会半生不熟,或者需要在某些地方进行可疑的工作。无论如何,某种隐藏的陷阱。到目前为止,WPF 已经完全免费 :)
    猜你喜欢
    • 2020-01-09
    • 1970-01-01
    • 2012-11-14
    • 2013-08-31
    • 2020-05-31
    • 2018-06-30
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    相关资源
    最近更新 更多