Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to show Messagebox in MVVM [duplicate]

Tags:

Possible Duplicate:
How have you successfully implemented MessageBox.Show() functionality in MVVM?

I want to show message box in my MVVM WPF application. so from where to call MessageBox.Show().

like image 390
Jeevan Bhatt Avatar asked Sep 14 '10 03:09

Jeevan Bhatt


2 Answers

In Windows Forms, or WPF without MVVM, you could just say MessageBox.Show() and that was it! Wouldn't it be nice if you could do the same in MVVM?

Here is one way to do this - and it is as close as I can get to MessageBox.Show().

Here is the MVVM friendly 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         }     } } 

Tada!

Here is how it works:

All that MessageBox_Show actually does is fire an event, so it is perfectly MVVM friendly. The ViewModel knows nothing about any view that may or may not be consuming it, and it doesn't perform the showing of a Windows MessageBox on it's own, so it can also be safely unit tested.

To use it in a View, which will cause it to actually show a MessageBox, you just subscribe to the event and call e.Show() in the event handler, like this:

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();     } } 

And that is all you need to do to show MVVM friendly Windows MessageBoxes.

The code below only needs to be implemented once in your project, or you can put it in a reusable shared library.

Add this to your ViewModel base class so it can be used from any 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));         }     } } 

And then add the EventArgs class for the event handler:

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);     } } 

Unit testing is easy:

target.AskTheQuestion(); target.ProcessTheAnswer(System.Windows.MessageBoxResult.Yes); 

Happy Coding!

like image 108
Harlow Burgess Avatar answered Sep 21 '22 06:09

Harlow Burgess


I've found that MVVM invokes a streak of OCD in programmers (I know from experience). That's a good thing. But for certain things the effort just isn't worth it, especially if it introduces an entire order of complexity just to ask the user "Are you sure you wish to xxxx?"

My opinion is that MessageBox.Show() may be called from the code-behind, but never the ViewModel. Until dialog boxes integrate better with XAML, just take the hit and don't feel bad about it. It's really a gray area of the current state of WPF UI design.

like image 36
bufferz Avatar answered Sep 24 '22 06:09

bufferz