创建一个MVVM友好的对话框策略。

22

我正在尝试创建一种处理弹出窗体的策略,以在我的应用程序的任何部分中使用。我的理解是,我需要在MainWindow的根目录下拥有一个单独的UserControl,并将其绑定到自己的ViewModel,该ViewModel将处理发送到应用程序内部的消息。

我正在使用MVVM Light,并且对Messenger类还比较陌生。

想象一下Master/Details场景,其中对象列表包含在ListBox中。选择其中一个项目并单击编辑按钮将显示一个覆盖整个屏幕的UserControl。然后用户可以编辑所选项目,并单击OK以提交更改。

我希望打开的UserControl可以“通用”,以便我可以将任何东西(可能是ViewModel)传递给它... 通过DataTemplate呈现ViewModel并处理所有对象更改。点击OK会回调到发送类并像以前一样持久化更改。

以下是一些这将非常有用的情况...

  1. 显示无需用户输入的错误消息(仅需要单击确定即可关闭它)
  2. 显示数据项的编辑表单
  3. 确认对话框(与标准MessageBox类似)

有人能提供任何代码示例,以展示我如何实现这一点吗?

3个回答

21

使用MVVM设计UI的目标是将View和ViewModel的职责分离。理想情况下,ViewModel不应该依赖任何视图组件。但是,这只是理想情况,MVVM的另一个规则是您应该按照您的意愿设计应用程序。

在提供显示对话框服务的领域中,有两种不同的方法:

  1. 在View上实现DialogService(例如,请参见http://geekswithblogs.net/lbugnion/archive/2011/04/13/deep-dive-mvvm-samples-mix11-deepdivemvvm.aspx示例03)。
  2. 实现未附加到视图的服务组件(例如,请参见http://blog.roboblob.com/2010/01/19/modal-dialogs-with-mvvm-and-silverlight-4/)。

这两种方法都依赖于定义服务功能的接口,然后将该服务的实现注入到ViewModel中。

此外,这两种方法都有各自的优缺点。

  • 第一种方法也适用于WP7,但需要一个公共视图基类,因为它包含了视图服务的实现。
  • 第二种方法适用于SilverLight和WPF,并且很有吸引力,因为它将服务与视图分开并不对视图施加任何限制。

另一种可能的解决方案是使用消息来显示对话框。

无论您使用何种方法,请尝试使用IoC(控制反转)模式将视图和ViewModel解耦,即定义一个接口以便使用不同的实现。要将服务绑定到ViewModel中,请使用注入,即通过将服务传递到ViewModel的构造函数或设置属性来实现。


7
我最近开始学习MVVM,用于创建WPF应用程序。我使用这篇文章作为显示对话框的基础。如果您下载示例项目,那么它实际上是一种不错的解耦方法,它被很好地抽象化,要获取视图,您需要传递一个视图模型的实例。我为自己的目的进行了一些扩展,还使用了WPFExtendedToolkit MessageBox来显示警告、错误等,因为标准的win32 MessageBox看起来很丑。
关于动态表单,您需要研究ItemsControl,并在您的ViewModels中拥有一个数据项集合,用户需要编辑这些数据项以便让ItemsControl进行绑定。我在工作流系统设计器中有一个用于编辑操作及其参数的对话框,在该对话框中,操作列表完全是动态的。这是通过公开我的项目集合及其数据类型来完成的,因此我可以使用DataTemplateSelector选择包含正确类型控件的DataTemplates,例如日期时间数据类型将显示DatePicker。
希望这可以帮到您。

2

从一个开发者的角度来看,维护那个通用代码似乎很麻烦。根据您所描述的,我会给表单和对话框使用相同的视图模型,并创建一个特定的XAML模板,以展示您想要显示的对话框。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接