views:

3515

answers:

6

Does anyone have any examples of showing a window dialog using MVVM (Prism)? - for example a configuration settings window when a command is executed.

All of the examples I've seen use the mediator pattern which is fine, but they also all have a reference to the view in the view model which is not ideal (we're using DataTemplates)

Thanks

+4  A: 

The way I do this is using the mediator pattern also. When the ViewModel wants to show a dialog, it sends a message which is picked up by the application's main window. The message contains an instance of the ViewModel used by the dialog.

The main window then constructs an instance of the dialog window, passes the view model to it and shows the dialog. The result of the dialog is passed back to the caller in the original message.

It looks something like this:

In your view model:

DialogViewModel viewModel = new DialogViewModel(...);
ShowDialogMessage message = new ShowDialogMessage(viewModel);

_messenger.Broadcast(message);

if (message.Result == true)
{
    ...
}

In the main window codebehind:

void RecieveShowDialogMessage(ShowDialogMessage message)
{
    DialogWindow w = new DialogWindow();
    w.DataContext = message.ViewModel;
    message.Result = w.ShowDialog();
}

I hope this is enough to give you the idea...

Groky
Thanks for the answer. Could you clarify the below scenario please.Say you display a view model in the DialogWindow with Save and Cancel commands. When the user clicks Save on the view (bound to the SaveCommand) you would want to maybe run some validation and save the configuration, only if this is successful would the dialog close.I can't seem to get my head around how the VM would set the DialogResult of the view (therefore closing the dialog).Thanks again.
Oll
There are many ways of getting the VM to interact with the view without breaking the abstraction. For instance, the dialog view model base class typically has some base properties and methods to make showing dialogs a little easier (I typically have a interface for a dialog viewmodel that includes things like a method that is meant to run on view load, as well as the dialog result, commit/abort commands, etc). An easy way to get the viewmodel to tell the view to close is to expose a property (CanClose for instance).
Egor
Then create a corresponding dependency property on your dialog, and when the datacontext changes set a binding between the two - that way you can handle any logic in your bound property's changed event handler. Then again, it's even easier to simply expose a "close" event on your dialog viewmodel, and in the dialog window data context changed handler subscribe to this event, the handler can assign appropriate dialog result and close the window.
Egor
A: 

You might be interested in the following sample application:

http://compositeextensions.codeplex.com

It uses Prism2 with the PresentationModel (aka MVVM) pattern. The sample application contains a modal dialog.

jbe
A: 

As I understood your comment above, the question is not so much about showing the dialogs as about hiding them. There are two ways to solve this problem:

  1. Use standard dialog window to implement the view. This would require to have a loosely coupled way of communication between View and ViewModel so that ViewModel can notify the View that it's ok to close without having a reference to a view.

    There are multiple frameworks exist that would allow to do it - Prism's event aggregators would be one of them. In this scenario View would subscribe to an event (say, MyDialogResultValidated), and on receiving the event it would set the DialogResult accrodingly. ViewModel (in its SaveCommand) would fire the event if validation was successful.

  2. Don't use standard dialog window to implement the view. This would require to have an overlay that would effectively emulate modality.

    In this scenario the Visibility of the View and of the overlay will be bound ViewModel's IsVisible property that would be set accordingly by SaveCommand implementation, or whenever ViewModel needs to show the View.

The first approach would require having a bit of code in code-behind, requires adding global event(s), and (arguably) is less MVVM-ish. The second approach would require implementing (or using someone else's implementation) of the overlay, but won't require having any code in code-behind, won't require having global event(s), and is (arguable) more MVVM-ish.

PL
+3  A: 

I would use a service to display the dialog. The service can then also link views with viewmodels.

public interface IDialogService {
    void RegisterView<TView, TViewModel>() where TViewModel:IDialogViewModel;
    bool? ShowDialog(IDialogViewModel viewModel);
}

public interface IDialogViewModel {
    bool CanClose();
    void Close();
}


RegisterView just links the view type with the ViewModel type. You can set up these links in the module initialization. This is simpler than trying to get modules to register datatemplates in the top layer of your application.

ShowDialog Shows the ViewModel you want to display. It returns true, false and null for close just like the Window.ShowDialog method. The implementation just creates a new view of type TView from your container, hooks it up to the provided ViewModel, and shows it.

IDialogViewModel provides a mechanism for the ViewModel to do verification and cancel the closing of the dialog.

I have a standard dialog window, with a content control in it. When ShowDialog is called it creates a new standard dialog, adds the view to the content control, hooks up the ViewModel and displays it. The standard dialog already has [OK] and [Cancel] buttons with the appropriate logic to call the right methods from IDialogViewModel.

Cameron MacFarland
A: 

It isn't Prism, but this MVVM demo has an Options Dialog that's fully MVVM.

Scott Whitlock
A: 

Below are two posts that show how to use/handle dialogs, they include viewable samples and code:

http://www.orktane.com/Blog/post/2009/10/23/Web-Xcel-Demo-View-Services-in-nRoute.aspx http://www.nikhilk.net/ViewModel-Dialogs-Task-Pattern.aspx

Hope that helps

Rishi