在WPF的MVVM模式中,处理对话框是比较复杂的操作之一。由于视图模型不知道视图的任何信息,因此对话框通信可能会很有趣。我可以公开一个ICommand,当视图调用它时,就会出现一个对话框。

有人知道处理对话框结果的好方法吗?我说的是windows对话框,比如MessageBox。

其中一种方法是在视图模型上设置一个事件,当需要对话框时,视图会订阅该事件。

public event EventHandler<MyDeleteArgs> RequiresDeleteDialog;

这是可以的,但这意味着视图需要代码,这是我想要避免的。


当前回答

我目前的解决方案解决了你提到的大部分问题,但它完全从特定于平台的东西中抽象出来,可以重用。 此外,我使用了没有代码隐藏,只与实现ICommand的DelegateCommands绑定。 对话框基本上是一个视图——一个独立的控件,它有自己的ViewModel,它从主屏幕的ViewModel显示,但通过DelagateCommand绑定从UI触发。

查看完整的Silverlight 4解决方案在这里与MVVM和Silverlight 4模态对话框

其他回答

我目前的解决方案解决了你提到的大部分问题,但它完全从特定于平台的东西中抽象出来,可以重用。 此外,我使用了没有代码隐藏,只与实现ICommand的DelegateCommands绑定。 对话框基本上是一个视图——一个独立的控件,它有自己的ViewModel,它从主屏幕的ViewModel显示,但通过DelagateCommand绑定从UI触发。

查看完整的Silverlight 4解决方案在这里与MVVM和Silverlight 4模态对话框

我认为处理对话框应该是视图的责任,视图需要有代码来支持这一点。

如果你改变ViewModel - View交互来处理对话框,那么ViewModel依赖于该实现。处理这个问题最简单的方法是让视图负责执行任务。如果这意味着显示一个对话框,那么很好,但也可以是状态栏中的状态消息等。

我的观点是,MVVM模式的全部观点是将业务逻辑从GUI中分离出来,因此您不应该在业务层(ViewModel)中混合GUI逻辑(以显示对话框)。

Karl Shifflett创建了一个使用服务方法和Prism InteractionRequest方法显示对话框的示例应用程序。

我喜欢这种服务方式——它不太灵活,所以用户不太可能弄坏东西:) 它也与我的应用程序的WinForms部分(MessageBox.Show)一致。 但如果您计划显示许多不同的对话框,那么InteractionRequest是更好的方法。

http://karlshifflett.wordpress.com/2010/11/07/in-the-box-ndash-mvvm-training/

在学习(仍在学习)MVVM时,我真的为这个概念挣扎了一段时间。我的决定,以及我认为其他人已经决定但我不清楚的是:

我最初的想法是ViewModel不应该被允许直接调用对话框,因为它没有业务决定对话框应该如何显示。正因为如此,我开始思考如何像在MVP(即View.ShowSaveFileDialog())一样传递消息。然而,我认为这是错误的方法。

ViewModel直接调用对话框是可以的。然而,当您测试ViewModel时,这意味着对话框要么在测试期间弹出,要么全部失败(从未真正尝试过这个)。

因此,在测试时需要使用对话框的“测试”版本。这意味着,对于您拥有的任何对话,您都需要创建一个Interface,并模拟对话响应,或者创建一个具有默认行为的测试模拟。

您应该已经在使用某种服务定位器或IoC,您可以对其进行配置,以便根据上下文提供正确的版本。

使用这种方法,你的ViewModel仍然是可测试的,根据你如何模拟对话框,你可以控制行为。

希望这能有所帮助。

最简单的方法:使用HanumanInstitute。MvvmDialogs图书馆

如果您遵循文档,您可以像这样漂亮地使用它,并与UI完全解耦

var presetName = await dialogService.ShowSavePresetViewAsync(this);