MahApps MessageBoxes using MVVM
As of 1.1.3-ALPHA* (to become 1.2.0) MahApps provides a helper to launch dialogs from a VM, which works in a multiple Window setup:
1) Use an attached property in your Window to register your view model with the dialog sub-system.
Assuming your View’s DataContext is set to the view model from where you want to launch the dialog, add these attributes:
<Controls:MetroWindow
xmlns:Dialog="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
Dialog:DialogParticipation.Register="{Binding}">
2) Grab/inject DialogCoordinator:
new MainWindowViewModel(DialogCoordinator.Instance);
3) Show your dialog from the view model. Use "this" as the context so MahApps can marry your view model to the correct window:
_dialogCoordinator.ShowMessageAsync(this, "Message from VM", "MVVM based dialogs!")
I have created a wrapper to call the MahApps.Metro message dialog, cause I was having the same problem with my MVVM project. I had to create a list of opened windows, which the first window will always be my MainWindow.
Here's my DialogService
code:
public async Task<MessageDialogResult> ShowMessage(string message, MessageDialogStyle dialogStyle)
{
var metroWindow = (_openedViews.First() as MetroWindow);
metroWindow.MetroDialogOptions.ColorScheme = MetroDialogColorScheme.Accented;
return await metroWindow.ShowMessageAsync("MY TITLE", message, dialogStyle, metroWindow.MetroDialogOptions);
}
This code can be used to show dialogs with or without a result. You can notice that its return is a Task<MessageDialogResult>
, so if you want to get the result, you can do just like that on your ViewModel:
MessageDialogResult result = await _dialog.ShowMessage("SOME MESSAGE HERE", MessageDialogStyle.AffirmativeAndNegative).ConfigureAwait(false);
if (result == MessageDialogResult.Affirmative)
{
//Do something
}
By the way, if the method that calls the ShowMessage()
needs a result, you MUST put async
on the assignment, otherwise it won't work. (if you only want to show a message dialog, it's not necessary).
My project is using Framework 4.0, and I can only use async/await
due to the package I had to install from NuGet.
You can acces this link for the MSDN documentation of this package, and you can download the package here.
I hope it has solved your problem.
EDIT:
I have implemented a method on my DialogService
to open any windows from any ViewModel. This method uses Microsoft Unity
framework to instantiate my object, and then I call Show()
to open itself. Before a call Show()
, I add this window on a list.
See my code:
public void ShowView<T>(params ParameterOverride[] parameter)
{
var window = UnityServiceConfigurator.Instance.Container.Resolve<T>(parameter) as MetroWindow;
if (window != null)
{
if (Application.Current.MainWindow != window)
{
window.Owner = Application.Current.MainWindow;
var ownerMetroWindow = (window.Owner as MetroWindow);
if (!ownerMetroWindow.IsOverlayVisible())
ownerMetroWindow.ShowOverlayAsync();
}
if (!_openedViews.Contains(window))
_openedViews.Add(window);
window.Show();
}
}
This is how I call from my ViewModel:
_dialog.ShowView<MyView>();
If you have only one window on your entire software, you can save its reference and use it to show the ShowMessageAsync()
without needing to create a List only to use the First. Like this:
var metroWindow = (Application.Current.MainWindow as MetroWindow);