views:

2733

answers:

4

I am implementing MVP/M-V-VM in WPF and I'm having good luck with it so far. However, I don't see how this model supports implementing Modal dialog boxes. I've derived my work from Crack.NET (http://www.codeplex.com/cracknetproject) to learn how this stuff works.

I have a ShellView view (which is just XAML) that has a menu on it. The menu binds to a command in the ShellModelView that says "EditPreferences".

The ShellModelView implements the ICommand for EditPreferences and here we want to put up a dialog box to let the user edit preferences for the application.

Several problems here: 1. The ShellModelView doesn't have a reference to the ShellView to properly parent the dialog. The ShellModelView is the DataContext of the ShellView but I don't see a backreference that's setup. 2. The ShellModelView shouldn't be loading explicit UI anyway. So what's the proper interaction model here? 3. How do I build up my PreferencesDialog so that it's properly separated between logic and view as well? PreferencesDialog itself needs to be a Window so you can call ShowDialog on it, but that means you need a reference to the Window (e.g. View) in order to instantiate it. Ideally I should be able to unit test the code/validation within PreferencesDialog without instantiating the view (using a Mock view perhaps?).

+1  A: 

You will need a controller in your case. The controller should be in charge for showing the preference dialog window.

As I can envision it the controller should be responsible for creating the ShellModelView and binding view's DataContext to it. The controller should be also responsible for handling command execution of EditPreferences. In the execution logic the controller will create a new PreferencesDialog and its corresponding view model.

You can find similar patterns in Prism if you haven't already did it. You can also reuse the DelegateCommand provided there :)

ligaz
+4  A: 

Perhaps this is not the appropriate way to look at it, but this is the approach I take with M-V-VM in WPF. Opening windows and dialog boxes or an "EditPreferences" view are UI specific functions. If I were to rewrite the your entire UI replacing all of the views, I may wind up combining the "EditPreferences" view with another view, and therefore never want to open it in another screen. If this were tied to the ViewModel, it would be difficult to get around. In this particular situation, I would have a button or menu item in my "ShellView" that creates a new instance of my "EditPreferences" view, and then passes in the "EditPreferences" ViewModel which may either come from a property in my "ShellViewModel", or perhaps my "EditPreferences" view instantiates the ViewModel itself.

Here is a similar question on SO that basically says the same thing: M-V-VM Design Question. Calling View from ViewModel

Micah
+1  A: 

Have the PreferencesDialog implement a interface that is one of the properties of the EditPreference command. The command would interact with the dialog through the interface. For Unit Testing the mock object would implement the interface instead.

The dialog class then can reside on your highest layer.

RS Conley
I thought one of the goals of MVVM is to achieve not having the ViewModel know a thing about the View (or dialog in your example)? So that any number of Views (or none) may be using a ViewModel at any time. Having your ViewModel set things on an View interface kinda breaks that.
Simon Brangwin
It doesn't because the interface insulate the command from the implementation of the dialog.
RS Conley
That's MVP pattern. Changing your suggested View interface would break the ViewModel, e.g. change the signature of a method or type of a property, BAM you just broke your ViewModel that has a dependency on the interface. In MVVM, the view 'observes' the ViewModel via Bindings. Making changes to the View (e.g. adding controls) won't require changing interfaces or even recompiling the ViewModel. Cool thing is, a single ViewModel can be 'observed' by many Views. See Observer pattern in GOF book and read Prism docs section 'Presentation Model' if you're interested more in this :)
Simon Brangwin
A: 

My 2 cents is:

  1. Pass some kind of viewfactory contract as the command parameter or inject a viewfactory contract into the view model. The view model will them use the viewfactory to create any modal/non modal views it needs. The viewfactory could also take in as a parameter of its Show/ShowModal method a viewmodel to display. Furthermore, the viewfactory could use a datatemplate to display any viewmodal passed in as a parameter.

  2. Add a ShowViewModel property to the viewmodel in question. A DataTrigger could then watch for this property and when it is of a particular type show the view, etc.

Kess