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

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

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

public event EventHandler<MyDeleteArgs> RequiresDeleteDialog;

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


当前回答

我遇到了同样的情况,并将MessageBox包装成一个设计器不可见控件。详情在我的博客里

http://geekswithblogs.net/mukapu/archive/2010/03/12/user-prompts-messagebox-with-mvvm.aspx

同样可以扩展到任何模态对话框,文件浏览控件等。

其他回答

一个有趣的替代方法是使用控制器来显示视图(对话框)。

WPF应用程序框架(WAF)说明了这是如何工作的。

我已经实现了一个从ViewModel监听消息的行为。它基于Laurent Bugnion的解决方案,但由于它不使用代码,而且更可重用,所以我认为它更优雅。

如何使WPF的行为,如果MVVM是支持开箱即用

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

编辑:是的,我同意这不是一个正确的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:如何关闭一个窗口

我遇到了同样的情况,并将MessageBox包装成一个设计器不可见控件。详情在我的博客里

http://geekswithblogs.net/mukapu/archive/2010/03/12/user-prompts-messagebox-with-mvvm.aspx

同样可以扩展到任何模态对话框,文件浏览控件等。