【问题标题】:How should the Model let the ViewModel know about changes in its state?Model 应该如何让 ViewModel 知道其状态的变化?
【发布时间】:2012-11-12 06:56:25
【问题描述】:

我正在构建和 MVVM 应用程序,其中我的一些模型包含他们正在建模的真实世界对象的状态。状态从外部事件改变,例如我的模型通过 TCP/IP 获取有关股票变化的信息,并更新其状态以反映该变化。

现在我希望将更改传播到我的视图,而这样做的方法是让我的 ViewModel 知道更改。 我可以想到两种方法来做到这一点。

,我让Model实现INotifyPropertyChanged,当属性改变时触发事件。但是,出于某种原因,这似乎是frowned upon
,我为模型中可以更改的每个属性实现了一个事件,ViewModel 可以显式绑定到的事件。 p>

首选方式是什么?还有其他方法(更好的方法)吗?

编辑:
我现在已经在comment from slugsterhere 中读到,让模型拥有状态并不是模型的目的。
然而,在 John Gossman 的原始 MVVM post 中,我们发现:“模型在 MVC 中定义;它是完全独立于 UI 的数据或业务逻辑,存储状态并执行问题域的处理。”

【问题讨论】:

    标签: c# mvvm


    【解决方案1】:

    选项 2 是可行的,尽管很脏。你可以通过一个接口暴露公共事件和函数来减轻这种肮脏,而视图模型仅通过该接口使用模型。

    话虽如此,模型应该被视为信息的管道,而不是信息的容器。这意味着理想情况下,您的模型不应包含任何状态信息。如果您的模型中有一个持续打开的通道,需要在收到某些内容时通知其他组件,那么我建议您在 Prism 中使用 EventAggregator - 这是一个弱事件发布/订阅系统,您的视图模型可以订阅您的选择,并且您的模型可以在需要时发布该事件(以及适当的有效负载)。

    【讨论】:

    • 让模型有状态的好处是你可以在没有视图的场景中使用它。如果状态没有进入模型,它就必须进入视图模型。有一个没有视图的视图模型似乎很奇怪。拥有一个 EventAggregator 似乎对于这个问题来说太正交了。
    【解决方案2】:

    模型类通常提供属性和集合更改 通过 INotifyPropertyChangedINotifyCollectionChanged 接口。这使他们可以轻松地 数据绑定在视图中。表示集合的模型类 对象通常派生自 ObservableCollection 类。

    MSDN

    我不会说模型通常会实现 INotifyPropertyChanged,但我不会断然拒绝这样做。在我看来,在更简单的非 PRISM 环境中它完全没问题。

    然后呢?

    澄清一下:INotifyPropertyChanged 是一个用于通知属性更改的接口,正如其名称和大多数人所知道的那样。但是,仅此而已,尤其是它不是特定于 WPF 的!此外,根据 MVVM 原则,Model 应该与 ViewModel 无关。因此,很明显,您应该使用 Publisher(Model)-Subscriber(ViewModel)-模式(事件)。就这样。因此,作为对您问题的回答:如何设置 Model/ViewModel 之间的通信取决于您的风格和具体任务:

    如果您只想对更改的属性做出反应,只需使用 INotifyPropertyChanged,因为它就是为此而生的。在 ViewModel 中,只需订阅 ModelPropertyChanged-事件并处理更改,这基本上只是“将它们向前映射”,即为 ViewModel 属性提高 PropertChanged,这受 model 属性更改的影响。

    或者,如果您需要将模型更改包装在更具体的事件中,比如“MyDataUpdated”,那么我也没有看到任何问题。只需在 ViewModel 中侦听此事件,并根据需要进行处理。没关系。

    我希望这会有所帮助。

    编辑:附带说明:我建议使用 PropertyWeaver 扩展,这样您就不会因为所有 PropertyChanged 的​​东西而弄乱您的模型。

    【讨论】:

    • 很酷的扩展。然后通常会做什么?模型如何更新 ViewModel?
    【解决方案3】:

    我会选择选项1。在视图模型中保留对模型的引用,但不要直接使用任何属性。相反,从模型中填充视图模型自己的属性。您的视图模型可以从模型中监听相关属性的属性更改通知,并从模型中重新填充它自己的属性。该模型仍然独立于 UI,它只是通知属性更改。

    在我看来,除了 inotifypropertychanged 之外,执行您自己的发布者-订阅者逻辑可能只是矫枉过正,因为这样做可能没有任何好处。但是,这取决于您是否有能力在视图模型中拥有模型引用,我的回答是基于您可以在视图模型中拥有模型引用的假设

    【讨论】:

      【解决方案4】:

      对于数据绑定,您可以使用 **Binding**

      Data Binding Overview

      【讨论】:

      • 这并不能真正回答问题 - OP 已经知道绑定。我也绝不会提倡在 MVVM 模式中从视图绑定到模型。
      猜你喜欢
      • 2017-02-13
      • 2017-01-26
      • 2021-11-09
      • 1970-01-01
      • 2016-11-14
      • 2020-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多