Prism WPF + MahApps modal window the MVVM way - part 2

Tags: wpf, prism, mahapps, mvvm, modal

Last time we finished with all the pieces except the common:MahAppsPopupWindowAction used in XAML. Prism already has a PopupWindowAction (it wasn't there a few years ago) so let's use that to create our own popup window action that will show MahApps-metro-style-dialog.

The complete source code for this class is in this gist:

Let's briefly go over it.

First of all, we need to create MahApps MetroWindow class instead of default WPF window and that's what is being done in Window CreateWindow() method. I've taken the window settings from MahApp source code of modal dialog.

The parent MetroWindow for our modal is obtained in MetroWindow metroWindow property.

So far so good.

Our window will be shown using standard ShowDialog() method, which is already done by Prism PopupWindowAction.Invoke(object parameter) method. But we would also like to display a MahApps overlay to give it even more metro-like look and that's what is being done in our overridden Window GetWindow(INotification notification).

Specifically, we want to show overlay immediately and want to hide it when window is being closed so we need to hook up to Closed event.

However, there's one caveat: MetroWindow has two methods: ShowOverlay() and ShowOverlayAsync(). The second one just uses overlay opacity animation (that lasts 0.3 seconds or so) which is nicer but can pose some problems: when the user calls our action to first show, and then almost immediately to hide our modal, then the HideOverlayAsync() method might return immediately since there's no overlay yet, but at the same time the animation started in ShowOverlayAsync() will continue and the overlay will appear. So that's why I propose to stick with ShowOverlay(). I guess it should probably be possible to fix it in MahApps and who knows, maybe someday I'll take my shot at it.

Right now we are already handling showing of the modal and the overlay. Note that we don't have to do anything with window's content because Prism is already doing everything for us in that matter.

But I wanted to display busy indicator using this technique, so it's reasonable to suppress the user from closing this window (by ALT+F4). Unfortunately, it's not that easy in WPF as in WinForms, which has just a proper event in which you can just cancel window closing.

One solution to this problem is to add a custom temporary windows message hook which will check if closing is being done by the user. I found it somewhere, probably on StackOverflow, but I can't recall precise URL. Anyway, the most important thing is that it works.

So there you have it. A complete handling of showing/hiding MahApps windows using Prism, in an MVVM way. If you haven't seen part 1, then check it out because you'll find other pieces of the puzzle there.

Read also

Prism WPF + MahApps modal window the MVVM way - part 1

Showing MahApps modals in a Prism WPF and MVVM friendly way (part 1).

Templating in .NET

Hardcoding strings is one of the biggest crimes in programming. Seriously, you should never do this. Instead, use one of the templating engines for an easy and flexible content generation.

Passing struct array in struct via P/Invoke

So you want to use some super-cool and fast C/C++ library from your C# code? Prepare yourself for struggle with P/Invoke then.