tags:

views:

321

answers:

2

I'm using M-V-VM with dialog boxes. The process I'm using for creating dialogs is as follows:

  • A ViewModel command wishes to open a dialog.
  • It creates the ViewModel for the dialog (we'll call it DialogViewModel).
  • It then passes the ViewModel off to a DialogProvider to create the actual View. This makes my dialog boxes testable, as the provider can provide either a the real view or a test view.

I have this all working. However, currently my solution for DialogProvider is to use reflection to manually find the View class to instantiate based on the name of the ViewModel, like so:

var viewModelType = viewModel.GetType();
var dialogTypeName = Regex.Replace(viewModelType.Name, "ViewModel$", "Dialog");
var viewType = Assembly.GetExecutingAssembly().GetType(dialogTypeName);
if (viewType == null)
    throw new InvalidOperationException("Could not find view for given type.");

var dialog = (Dialog)viewType.GetConstructor(Type.EmptyTypes).Invoke(new object[0]);
dialog.DataContext = viewModel;
dialog.Owner = Application.Current.MainWindow;

return dialog;

This is suboptimal, as the View must be named the same as the ViewModel, and must be in the same namespace, etc.

Ideally I would use the DataTemplate machinery to do this. What I would like to do is the same as using a DataTemplate for a view, and using a ContentPresenter to choose the view based on the DataTemplate's DataType attribute (see Josh Smith's MVVM article. However, I need to do this in C# code (within the DialogProvider).

Is this possible? I'm imagining things like creating a ContentPresenter in C#, settings it's DataTemplate, and then reaching it to pull the Dialog view out???

Eric

+3  A: 

Why not just have the DialogProvider use a default View that is nothing but a Window containing a ContentPresenter.

You could then merge the window resources with your current window resources (this would let a DataTemplate for your new ViewModel map to the appropriate View, defined as a UserControl).

Once you've done that, all you'd have to do is set the content of the ContentPresenter to your DialogViewModel from C#, and WPF would handle mapping the approriate View into place.

Reed Copsey
OK. Got it. That works. A warning to others trying this: Don't forget to set the Owner property on the dialog window. If you don't, WPF can't find the resources for the DataTemplate, and thus you get a dialog window containing the type name of the ViewModel instead of the appropriate View.
Eric
Reed -Ran into a problem. How do I set the Title and Size of the Dialog window from the DataTemplate? Eric
Eric
For the title: You'll need to do it from your DialogProvider, not via the DataTemplate. The size can be handled by setting it to auto - and just having the UserControl be sized appropriately.
Reed Copsey
+1  A: 

We use dependency injection (DI) to get the View (or Dialog) for the specified ViewModel. This approach let us to unit test the ViewModels with a MockView.

How this works can be seen in the ViewModel sample of the WPF Application Framework (WAF).

jbe