【发布时间】:2015-08-29 10:55:51
【问题描述】:
在过去的几个月里,我一直在尝试熟悉 wpf 中的 mvvm 模式。这是一个被广泛讨论的话题,我遇到了一些相互矛盾的文章。我知道 mvvm 是一种模式,而不是普遍的真理,但是在某些情况下确实找到了决定什么去哪里,什么做什么的灰色区域。 99% 的时间是在 viewmodel 和 view 之间出现这些问题。
我目前决定什么属于哪里的心态:
模型:它只包含要保存到文件中的数据。不多也不少。
ViewModel:是视图和与该视图关联的一个或多个模型之间的通信桥梁。
视图:处理视觉表示、视觉弹出和视觉修改
第一个关于模型的简单问题: (案例 1)
到目前为止,在我看到的每个实现中,模型对象都是实现 INotifpropertyChanged 的类。为什么模型应该是一个类而不仅仅是一个描述数据应该是什么的接口并让视图模型实现这个接口?模型不应该处理 ui,即使它是解耦的,因此给模型类 INotifyPropertyChanged 与让 viewmodel 从 DependencyObject 继承一样错误(即使我理解它在该类型的模型实现中的重要性)?
ViewModel 与 View 应该处理的灰色区域示例: (案例 2)
假设我正在创建一个 Uml 编辑器,其中有节点和连接器在视图模型中创建并保存在他们自己的 ObservableCollection 中。
<SomePageView.DataContext>
<vm:SomePageViewModel/>
</SomePageView.DataContext>
<Grid>
<ItemsControl ItemsSource="{Binding Nodes}" DataTemplate="{Binding SomeNodeUserControl}"/>
<ItemsControl ItemsSource="{Binding Connectors}" DataTemplate="{Binding SomeConnectorUserControl}"/>
</Grid>
当一个节点在网格周围拖动时,任何附加的连接器端点都将跟随该节点移动。我个人认为这是 UiElements 之间的通信,但是有两种完全不同的方式来实现这种行为。通过保持对 NodeviwModel 的完整引用来更新连接器,并使用其位置成员来更新连接器的位置。这是一种非常简单的方法,但不喜欢它,因为我认为它应该是更新 ConnectorVm 位置的 ConnectorView。这要求连接器视图了解特定的 NodeView。然而,这种方法更复杂,我还没有找到有效的解决方案(目前正在研究 EventAgregator 模式)。我喜欢最后一种方法的原因是,如果选择一个连接器,它应该是决定连接器如何移动的视图,而不是 ViewModel。对我的观察有什么建议或建议吗?
在 mvvm 模式中应该保留 ui 模式: (案例 3)
在 mvvm 中应该在哪里使用 eventAgregator、Mediator。在 ViewModel 或 CodeBehind 中?我目前的信念是它们属于背后的代码,但我对这件事有一点不确定性。如果保留在 codeBehind 中,我可以想象一种更简洁的方法,即使用带有加载事件的 VisualTree,而不是使用带有 Eventagregator 参数的构造函数等。 类似地,我可以实现一个不需要是单例的 UndoRedoController。应该更容易测试,可能有更多的 UndoRedoControllers 存在。一个示例可能是一个文档程序,它允许在选项卡中一次打开多个文档,因此应该有自己的 UndoController。
【问题讨论】:
-
这是什么意思“当一个节点在网格周围拖动时,任何附加的连接器端点都会跟随该节点移动”。您可以添加屏幕截图或解释一下吗?
-
模型还包含修改数据的方法。如果模型不提供任何更改通知,则视图模型必须定期检查以通知视图。这是不可取的。我还建议您添加一个示例应用程序并提出此示例说明的问题。通过这种方式,人们还可以检测出导致所需路径过时的设计缺陷。
标签: c# wpf design-patterns mvvm