tags:

views:

316

answers:

4

I'm using MVVM in a WPF app. I'm very new to both. Let me state that I am not a purest in the MVVM pattern, I am trying to use as many best practices as I can but am trying to make what I think are reasonable compromises to make it work in our environment. For example, I am not trying to achieve 0% code in my View codebehind.

I have a couple of questions about best practices.

1) I understand I don't want my VM to know about the attached View, but is it reasonable for the View to have a reference to its VM?

2) If a control in a View opens another View (such as a dialog) should I handle this in the View? It seems wrong to handle it in the VM since then the VM has some knowledge of a specific View.

+2  A: 

1). The view will need a reference to the view model at some level, since the viewmodel will act as the view's datacontext.

2) One way to handle this is to have a generalized viewmodel representing a dialog, that is owned by the main viewmodel (the one being used as the views datacontext.)

You can use a command to crate a new instance of a dialog viewmodel, which will have a corresponding datatemplate defined in your resources. This template will be set to bind to the dialogviewmodel type.

Pierreten
+1 but I think that for point 1), the OP was asking whether it is OK for the View class to know about the exact ViewModel class, rather than just bind on a datacontext of unknown type via property names.
Wim Coenen
Per Wim, indeed I was referring to the View class having a reference to the ViewModel, not just through databinding (which is abstract).
BrettRobi
On point #2. I'm using the MVVM Light toolkit in which I create Views, which then bind to a ViewModel through a Locator service. So I am not creating VM's, as they don't know how to attach a View to themselves. So it seems I need a way to create the dialog View, and where should that happen (View or VM)?
BrettRobi
+1  A: 

1) Here are two simple practices for View's "knowing about" a ViewModel. It's reasonable for a View to know about a ViewModel (for Data Binding) -- but you may not need it in your case. See if either of these approaches help solve your problem. There are other ways, but these should be simple enough:

public View(ViewModel vm)
{
     View.DataContext = vm;
}

public Bootstrapper(View v, ViewModel vm)
{
     v.DataContext = vm;
     //or, if you want it to have no parameters
     View v = new View();
     ViewModel vm = new ViewModel();
     v.DataContext = vm;
}

The first option isn't bad if you have a service location tool, but there is a flavor of MVVM that doesn't like any code in the View's Code-Behind. The second option isn't bad either, should be simple enough for your task.

2.) This question can be a bit of a sticky point in MVVM design. If we are talking about a general Win32 MessageBox, I will often separate that logic into an additional object and put it in the VM. This way tends to a little more clear. (For example, I have selected an item in a ListBox, I have attached a Delete ICommand to that action, and in my ViewModel when this ICommand is Executed, I will poke my MessageBoxObject to ask if the user "wants to really delete" this item). More advanced "Dialogs" would use additional ViewModels and DataTemplates for those ViewModels. I prefer the Mediator approach.

Jimmy Lyke
Thanks, the feedback is appreciated
BrettRobi
+3  A: 

1) The View has definitely a reference to the ViewModel through the DataContext. And you are allowed to cast the DataContext in your View:

public class ShellView : Window 
{
   …
   public ShellViewModel { get { return DataContext as ShellViewModel; } }

This isn’t a violation with the Model-View-ViewModel pattern.

.

2) You are right. A ViewModel shouldn’t open another View. A better approach is to use Controllers. They are responsible for the Workflow of an application.

If you are interested in more detailed information then you might have a look at the WPF Application Framework (WAF).

jbe
Kiff
Yeah, clearly the View knows about the VM through the DataContext, I guess I just hadn't seen that since all of the data binding in my xaml is so dependent on the VM that having a stronger reference to it in my Views codebehind hardly seems like a bad thing. And thanks for the tip on Controllers, I will look into that pattern.
BrettRobi
A: 

Build Your Own MVVM Framework

I found the approach suggested by Rob Eisenberg very interesting.

Key points:

  1. Convention over configuration
  2. ViewModel first

Which is very similar to ASP.NET MVC philosophy.

I highly recommend watching the video.