ViewModel如何知道服务中的数据何时更新?

时间:2009-03-14 06:54:36

标签: wpf mvvm idisposable

在我的应用程序中,我有几个ViewModel只有一个服务(存储库,DAO,等等),我们称之为 WidgetService ,注入它们。

假设其中一个ViewModel是所有用户小部件的列表。另一个可能是用于编辑/创建这些小部件中的单个小部件的ViewModel。

用户可以在 WidgetListViewModel 支持的 WidgetListView 中查看小部件列表,然后单击按钮添加新小部件。为了创建这个新的Widget, CreateWidgetViewModel 是新的并注入到某个UserControl / Window的DataContext中,因此,通过DataTemplates的魔力显示 CreateWidgetViewModel 强> CreateWidgetView 即可。此外, CreateWidgetViewModel 的新功能不一定发生在 WidgetListViewModel 的范围内。

WidgetListViewModel 注入了 WidgetService 的实例时。 CreateWidgetViewModel 注入了相同的 WidgetService 实例。

现在,当用户点击 CreateWidgetView 中的保存时,将会调用 WidgetService 上的保存方法并且小部件将被保留。现在需要通知 WidgetListViewModel 有一个新的Widget要显示!

长累积导致了这个问题:如何让 WidgetListViewModel 知道它需要显示新的Widget?

我见过Video,其中来自Microsoft的人使用ViewModel订阅的服务上的事件来做这种事情。但是,这种情况的结果是,如果服务比viewmodel更长,那么viewmodel将不会得到GC,直到服务是GC'd。我可以将IDisposable添加到ViewModel。但是当ViewModel仅通过DataTemplates在UI中表示时,何时/如何调用Dispose?

有人对此有任何建议吗?

澄清一下,我会说我对MVVM的解释与Josh Smith的解释最为相似。至少在我的MVVM架构中与Crack.Net源代码中的内容非常匹配。

5 个答案:

答案 0 :(得分:1)

好的,鉴于没有答案,但我想我会尝试一下,但我不是MVVM的专家。

事件似乎是这样的方式。但是,正如您所指出的,如果服务超过ViewModel,则可能存在内存泄漏。解决这个问题的最佳方法是使用弱事件监听器。

Weak Events允许你连接一个带弱引用的事件,这样如果源对象是GC'd,那么源不会被事件处理程序保持活动状态。

答案 1 :(得分:1)

使用Prism的(http://www.codeplex.com/CompositeWPF EventAggregator ,它使用发布者 - 订阅者模式,提供目标和源元素之间的失去耦合。完全适合您描述的场景。

答案 2 :(得分:0)

我使用Observer Pattern(又称发布/订阅模式)来解决同样的问题。我创建了一个名为EventAggregator的类,它拥有所有共享方法和数据成员。我可以在WidgetListViewModel上注册一个事件,并在CreateWidgetViewModel中发布一个“Widget Created”事件。您可以让WidgetListViewModel实现IDisposable(更好)来取消注册您的事件,或者您可以在Finalize方法中取消注册它。它运作得很好,最好的部分是两个视图模型不需要对彼此有任何想法。

对于更复杂的东西,或者如果你需要支持服务和应用程序之间的版本差异,你可以实现一个ModelView,它可以处理这种类型的东西,使你的应用程序的模式M-MV-VM-V。这似乎有点矫枉过正,但它可以使某些类别的问题更容易维护。我知道我有一些项目,我希望我插入一个MV,因为VM和撤消代码之间的串扰刚刚变得荒谬。

答案 3 :(得分:0)

有几种选择:

  1. 使用ObservableCollection - 这可能是最简单的选项,但你必须在模型中有一些“master”集合并让UI直接绑定到这个集合,这可能不是“干净”的MVVM架构但它可能是完成工作的最简单方法。

  2. 使用事件并确保自己清理,在MVVM中不容易。

  3. 使用一些中间人来自动清理事件(正如其他人建议的那样)但不写自己的事件,这里有很多陷阱,WPF有一个内置类可以做到这一点但是我忘记了姓名(如果有人记得这个名字,请发表评论)。

  4. 定期刷新,让ViewModel类每隔X秒刷新一次列表,这是获取更新的唯一方法,而不需要管理某种通知机制。

答案 4 :(得分:0)

我同意Cameron使用WeakEvent模式。我已经为ViewModel(在我的例子中使用名称PresentationModel)创建了一个支持WeakEvent模式的基类。

您可能会发现我的示例项目很有用:http://www.codeplex.com/CompositeExtensions

JBE