MahApps MessageBoxes using MVVM MahApps MessageBoxes using MVVM wpf wpf

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


If you have only one instance of your window showing, you can try something like this:

using System;using System.Collections.Generic;using System.Collections.ObjectModel;using System.ComponentModel;using System.ComponentModel.Composition;using System.Linq;using System.Text;using System.Threading.Tasks;using Caliburn.Micro;using MahApps.Metro.Controls;using MahApps.Metro.Controls.Dialogs;namespace Busyboy{    [Export(typeof(IShell))]    class MainViewModel : PropertyChangedBase, IShell    {        public void StartPomodoro()        {            var mainview0 = System.Windows.Application.Current.Windows.OfType<MainView>().FirstOrDefault();            mainview0.ShowInputAsync("New Pomodoro", "Enter a name for new pomodoro session.");        }    }}

And, you should have a way of identifying each window so you can filter out windows.Please note the import "Metro.Controls.Dialogs" which contains the extensions.