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.)
EDIT: More than 10 years after, I can tell that using a Mediator or any other messaging pattern is a really bad idea at so many levels. Don't do it, just implement Jeffrey's answer or a IDialogService injected in your view model.
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.