Handling Dialogs in WPF with MVVM
I suggest forgoing the 1990's modal dialogs and instead implementing a control as an overlay (canvas+absolute positioning) with visibility tied to a boolean back in the VM. Closer to an ajax type control.
This is very useful:
<BooleanToVisibilityConverter x:Key="booltoVis" />
as in:
<my:ErrorControl Visibility="{Binding Path=ThereWasAnError, Mode=TwoWay, Converter={StaticResource booltoVis}, UpdateSourceTrigger=PropertyChanged}"/>
Here's how I have one implemented as a user control. Clicking on the 'x' closes the control in a line of code in the usercontrol's code behind. (Since I have my Views in an .exe and ViewModels in a dll, I don't feel bad about code that manipulates UI.)
You should use a mediator for this. Mediator is a common design pattern also known as Messenger in some of its implementations. It's a paradigm of type Register/Notify and enables your ViewModel and Views to communicate through a low-coupled messaging mecanism.
You should check out the google WPF Disciples group, and just search for Mediator. You will be much happy with the answers...
You can however start with this:
http://joshsmithonwpf.wordpress.com/2009/04/06/a-mediator-prototype-for-wpf-apps/
Enjoy !
Edit: you can see the answer to this problem with the MVVM Light Toolkit here:
http://mvvmlight.codeplex.com/Thread/View.aspx?ThreadId=209338
A good MVVM dialog should:
- Be declared with only XAML.
- Get all of it's behavior from databinding.
Unfortunately, WPF doesn't provide these features. Showing a dialog requires a code-behind call to ShowDialog()
. The Window class, which supports dialogs, can't be declared in XAML so it can't easily be databound to the DataContext
.
To solve this, I wrote a XAML stub control that sits in the logical tree and relays databinding to a Window
and handles showing and hiding the dialog. You can find it here: http://www.codeproject.com/KB/WPF/XAMLDialog.aspx
It's really simply to use and doesn't require any strange changes to your ViewModel and doesn't require events or messages. The basic call looks like this:
<dialog:Dialog Content="{Binding Path=DialogViewModel}" Showing="True" />
You probably want to add a style that sets Showing
. I explain it in my article. I hope this helps you.