2

I am just getting started with WPF + MVVM. I think I’ve got the hang of the basics. However, I have a question (hopefully not a stupid one).

I have a View showing a list of customers. I want to edit one of these customers. How do I load the edit view with its separate ViewModel from the List ViewModel.

I’m sure this is a fairly standard scenario, with a fairly straightforward answer, but I’ve spent a chunk of time googling and come up with nothing concrete. Can someone point me in the direction of a straightforward example?

If I’m wrong and it’s not straightforward, what is the best way to do this type of thing?

John McArthur
  • 916
  • 1
  • 12
  • 30

1 Answers1

3

A common way of doing this (not only in MVVM but it applies well) is to give your list VM access to a so-called service. This service then implements creating and showing the editor (for which it probably uses yet another service).

Example:

/// Always use an interface for the service: it will make it a breeze
/// to test your VM as it decouples it from the actual service implmentation(s)
interface ICustomerEditorService
{
  /// Do whatever needed to get the user to edit the Customer passed in,
  /// and return the updated one or null if nothing changed.
  /// Customer here is likeyly your customer model, or whatever is neede
  /// to represent the editable data
  Customer EditCustomer( Customer toEdit );
}

class ListViewModel
{
  /// service gets passed to constructor, you can use dependency injection
  /// like MEF to get this handled easily;
  /// when testing, pass a mock here
  public ListViewModel( ...., ICustomerEditorService editorService )
  {
    ....
  }

  private void OnEditButtonClicked()
  {
    var editedCustomer = editorService.EditCustomer( GetSelectedCustomer() );
    //do stuff with editedCustomer
  }
}

/// A real implementation
class CustomerEditorService
{
  public Customer EditCustomer( Customer toEdit )
  {
    var vm = new CustomerEditorViewModel( toEdit );
    var view = new CustomerEditorView( vm );
    if( myWindowManager.ShowDialog( view ) == Cancel )
      return null;
    return vm.Customer;
  } 
}
stijn
  • 34,664
  • 13
  • 111
  • 163
  • Thanks. I've got this working. However, to do it I've had to create a public method on my MainWindowViewModel which handles opening all the views, and that just doesn't seem right, from what little I know about MVVM. Should I abstract this window opening away from that VM? – John McArthur Apr 10 '12 at 23:29
  • yes you should abstract that away, which is why in my example there is an 'IWindowManager' service which allows showing windows in some way. Eg the ShowDialog method could for example take any UserControl (in this case the editor View) and put it in a modal window having an Ok and Cancel button. In simple cases, you can have your MainWindowViewModel implement that interface directly. So it would still have that public method, but instead of passing the main VM around you pass it around as an IWindowManager so clients don't see the implementation details. – stijn Apr 11 '12 at 08:02