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().
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!
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With