如何在MVVM中显示Messagebox

Jee*_*att 17 wpf

可能重复:
您如何在MVVM中成功实现MessageBox.Show()功能?

我想在我的MVVM WPF应用程序中显示消息框.所以从哪里调用MessageBox.Show().

Har*_*ess 17

在Windows窗体或没有MVVM的WPF中,你可以说MessageBox.Show()就是这样!如果你能在MVVM中做同样的事情,那不是很好吗?

这是一种方法 - 它就像我可以到达MessageBox.Show()一样接近.

这是MVVM友好的MessageBox_Show()!

public class MyViewModel: ViewModelBase
{
    protected void AskTheQuestion()
    {
        MessageBox_Show(ProcessTheAnswer, "Are you sure you want to do this?", "Alert", System.Windows.MessageBoxButton.YesNo);
    }

    public void ProcessTheAnswer(MessageBoxResult result)
    {
        if (result == MessageBoxResult.Yes)
        {
            // Do something
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

田田!

下面是它的工作原理:

MessageBox_Show实际上所做的就是激活一个事件,因此它非常适合MVVM.ViewModel对任何可能使用或不使用它的视图一无所知,并且它不会自己执行Windows MessageBox的显示,因此它也可以安全地进行单元测试.

要在View中使用它,这将导致它实际显示MessageBox,您只需订阅该事件并在事件处理程序中调用e.Show(),如下所示:

public partial class MyView : UserControl
{
    public MyView()
    {
        InitializeComponent();

        this.DataContext = new MyViewModel();
        (this.DataContext as MyViewModel).MessageBoxRequest += new EventHandler<MvvmMessageBoxEventArgs>(MyView_MessageBoxRequest);
    }

    void MyView_MessageBoxRequest(object sender, MvvmMessageBoxEventArgs e)
    {
        e.Show();
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是显示MVVM友好的Windows MessageBox所需要做的全部内容.

下面的代码只需要在项目中实现一次,或者您可以将其放在可重用的共享库中.

将其添加到ViewModel基类中,以便可以从任何ViewModel使用它:

public class ViewModelBase : INotifyPropertyChanged
{
    //...

    public event EventHandler<MvvmMessageBoxEventArgs> MessageBoxRequest;
    protected void MessageBox_Show(Action<MessageBoxResult> resultAction, string messageBoxText, string caption = "", MessageBoxButton button = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None, MessageBoxResult defaultResult = MessageBoxResult.None, MessageBoxOptions options = MessageBoxOptions.None)
    {
        if (this.MessageBoxRequest != null)
        {
            this.MessageBoxRequest(this, new MvvmMessageBoxEventArgs(resultAction, messageBoxText, caption, button, icon, defaultResult, options));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后为事件处理程序添加EventArgs类:

public class MvvmMessageBoxEventArgs : EventArgs
{
    public MvvmMessageBoxEventArgs(Action<MessageBoxResult> resultAction, string messageBoxText, string caption = "", MessageBoxButton button = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None, MessageBoxResult defaultResult = MessageBoxResult.None, MessageBoxOptions options = MessageBoxOptions.None)
    {
        this.resultAction = resultAction;
        this.messageBoxText = messageBoxText;
        this.caption = caption;
        this.button = button;
        this.icon = icon;
        this.defaultResult = defaultResult;
        this.options = options;
    }

    Action<MessageBoxResult> resultAction;
    string messageBoxText;
    string caption;
    MessageBoxButton button;
    MessageBoxImage icon;
    MessageBoxResult defaultResult;
    MessageBoxOptions options;

    public void Show(Window owner)
    {
        MessageBoxResult messageBoxResult = MessageBox.Show(owner, messageBoxText, caption, button, icon, defaultResult, options);
        if (resultAction != null)resultAction(messageBoxResult);
    }

    public void Show()
    {
        MessageBoxResult messageBoxResult = MessageBox.Show(messageBoxText, caption, button, icon, defaultResult, options);
        if (resultAction != null) resultAction(messageBoxResult);
    }
}
Run Code Online (Sandbox Code Playgroud)

单元测试很简单:

target.AskTheQuestion();
target.ProcessTheAnswer(System.Windows.MessageBoxResult.Yes);
Run Code Online (Sandbox Code Playgroud)

快乐的编码!

  • 但是通过在ViewModelBase中使用对MessageBoxResult的System.Windows的引用,MessageBoxOptions是不是要破坏MVVM的目的? (5认同)
  • MVVM 的目标是将 UI 与逻辑分离,其中 ViewModel 不了解 View,并且您可以轻松地对 ViewMode 进行单元测试。它没有说你不能引用 System.Windows 命名空间,所以我在这里没有看到问题。对于事件来说,当事件发送者(ViewModel)的生存时间比事件监听者(View)的生存时间长时,就会导致泄漏。在这种情况下,ViewModel 和 View 通常具有相同的寿命,因此这里没有问题。但是,我会将代码从 ViewModelBase 移出到一个单独的类中。 (2认同)

buf*_*erz 8

我发现MVVM在程序员中调用了一连串的强迫症(我从经验中知道).这是好事.但是对于某些事情来说,努力是不值得的,特别是如果它引入了整个复杂的顺序,只是问用户"你确定你想要xxxx吗?"

我的观点是MessageBox.Show()可以从代码隐藏中调用,但从不调用ViewModel.在对话框与XAML更好地集成之前,只需点击即可,并且不要为此感到沮丧.它实际上是WPF UI设计当前状态的灰色区域.

  • 我正在使用命令,所以如果我必须在按钮的执行和执行功能后显示消息框,我需要传递一些数据来查看文件后面的代码,然后它将破坏mvvm. (4认同)