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

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

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

public event EventHandler<MyDeleteArgs> RequiresDeleteDialog;

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


当前回答

关于这个主题,我已经写了一篇相当全面的文章,还为MVVM对话框开发了一个弹出式库。严格遵守MVVM不仅是可能的,而且在正确实现时非常干净,而且它可以很容易地扩展到自己不遵守MVVM的第三方库:

https://www.codeproject.com/Articles/820324/Implementing-Dialog-Boxes-in-MVVM

其他回答

为什么不只是在VM中引发一个事件,然后在视图中订阅该事件呢?这将保持应用程序逻辑和视图分离,并且仍然允许您为对话框使用子窗口。

Sorry, but I have to chime in. I have been through several of the suggested solutions, before finding the Prism.Wpf.Interactivity namespace in the Prism project. You can use interaction requests and popup window action to either roll a custom window or for simpler needs there are built in Notification and Confirmation popups. These create true windows and are managed as such. you can pass a context object with any dependencies you need in the dialog. We use this solution at my work since I found it. We have numerous senior devs here and noone has come up with anything better. Our previous solution was the dialog service into an overlay and using a presenter class to make it happen, but you had to have factories for all of the dialog viewmodels, etc.

这不是小事,但也不是超级复杂。而且它是内置在Prism中,因此是最好(或更好)的实践。

我的2分钱!

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

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

编辑:10多年后,我可以看出使用Mediator或任何其他消息传递模式在很多层面上都是一个非常糟糕的主意。不要这样做,只需实现Jeffrey的答案或在视图模型中注入一个IDialogService即可。


你应该找个中间人。 Mediator是一种常见的设计模式,在某些实现中也称为Messenger。 它是一种Register/Notify类型的范例,允许ViewModel和Views通过低耦合消息传递机制进行通信。

你应该看看谷歌WPF门徒组,然后搜索调解员。 你会很高兴得到答案的……

但是你可以这样开始:

http://joshsmithonwpf.wordpress.com/2009/04/06/a-mediator-prototype-for-wpf-apps/

享受吧!

编辑:你可以看到这个问题的答案与MVVM轻工具包在这里:

http://mvvmlight.codeplex.com/Thread/View.aspx?ThreadId=209338

编辑:是的,我同意这不是一个正确的MVVM方法,我现在使用类似于由blindmeis建议的东西。

其中一种方法是

在你的主视图模型中(打开模态的地方):

void OpenModal()
{
    ModalWindowViewModel mwvm = new ModalWindowViewModel();
    Window mw = new Window();
    mw.content = mwvm;
    mw.ShowDialog()
    if(mw.DialogResult == true)
    { 
        // Your Code, you can access property in mwvm if you need.
    }
}

在你的模态窗口View/ViewModel中:

XAML:

<Button Name="okButton" Command="{Binding OkCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}">OK</Button>
<Button Margin="2" VerticalAlignment="Center" Name="cancelButton" IsCancel="True">Cancel</Button>

ViewModel:

public ICommand OkCommand
{
    get
    {
        if (_okCommand == null)
        {
            _okCommand = new ActionCommand<Window>(DoOk, CanDoOk);
        }
        return _okCommand ;
    }
}

void DoOk(Window win)
{
    <!--Your Code-->
    win.DialogResult = true;
    win.Close();
}

bool CanDoOk(Window win) { return true; }

或者类似于这里发布的WPF MVVM:如何关闭一个窗口