Model-View-ModelController – My take on MVVM – Introduction

January 9, 2009

I’ve seen a lot of examples from guys like Josh Smith and Karl Shifflett on best practices for using MVVM (Model-View-ViewModel). These are really great examples, but I have yet to find anyone doing real-world development in WPF on a LOB (line of business) application applying these principles.

I’m currently in development on a very large application and I will be writing a series of articles on the structure in which it is built including what I am calling Model-View-ModelController; a cross between MVVM and MVC. They obviously won’t entail any of the business specifics, but I want to demonstrate some of the patterns I am using to both give ideas to anyone struggling with the same issues I have and to also learn more through feedback from the community. Any and all feedback will be much appreciated.

The technologies I will be focusing on are WPF, and Linq-To-Sql. A few of the tenets I will be focusing on are

  • Views Instantiate the ModelControllers, and other Views
  • ModelControllers know NOTHING about the Views
  • ModelControllers instantiate Models and other ModelControllers
  • Models are simply DTO objects and have no knowledge of the existence of anything other than related Models

kick it on DotNetKicks.com

Advertisements

CommandBindings in MVVM

December 10, 2008

Anyone who has tried to implement RoutedCommands in WPF using M-V-VM has undoubtedly run into issues. Commands (non-UI commands that is) should be implemented in the ViewModel. For instance if I needed to save a CustomerViewModel then I would implement that as a command directly on my CustomerViewModel. However if I wanted to pop up a window to show the users addresses I would implement a ShowCustomerAddress command directly in the view since this a UI specific function.

The problem lies in the way that RoutedCommands find their associated CommandBindings. In order for a command to be executed it has to have a CommandBinding which tells it how to handle the Executed and CanExecute events. When you associate a control with a command it walks up the logical tree to find the first command binding associated with it. A typical scenario would look like this:

<UserControl>
<UserControl.CommandBindings>
<CommandBinding Command="ApplicationCommands.Save" CanExecute="Save_CanExecute" Executed="Save_Executed" />
</UserControl.CommandBindings>

<Button Command=”ApplicationCommands.Save” Content=”Save” />
</UserControl>

This approach forces us to define the behavior of of the command directly in our view, when really that logic should be in the ViewModel. So how do we get the the View to look for the CommandBindings in the ViewModel instead of the baked in behavior of searching up the logical tree? Well, we can’t. So instead, we need a way to get the CommandBindings out of the ViewModel and into the View. The first thing we need is a CommandBindingCollection property in our ViewModel:

private readonly CommandBindingCollection _CommandBindings;
public CommandBindingCollection CommandBindings
{
   get
   {
      return _CommandBindings;
   }
}

Now we create our CommandBindings and add them to the CommandBinding property we created:

public CustomerViewModel(Customer model)
{
//Create a command binding for the Save command
CommandBinding saveBinding = new CommandBinding(ApplicationCommands.Save, SaveExecuted, SaveCanExecute);

//Register the binding to the class
CommandManager.RegisterClassCommandBinding(typeof(CustomerViewModel), saveBinding);

//Adds the binding to the CommandBindingCollection
CommandBindings.Add(saveBinding);
}

Now with a little Attached Property goodness we add the commandbindings of our ViewModel to our View:

public static DependencyProperty RegisterCommandBindingsProperty =  DependencyProperty.RegisterAttached("RegisterCommandBindings", typeof(CommandBindingCollection), typeof(AttachedProperties), new PropertyMetadata(null, OnRegisterCommandBindingChanged));

public static void SetRegisterCommandBindings(UIElement element, CommandBindingCollection value)
{
if(element != null)
element.SetValue(RegisterCommandBindingsProperty, value);
}
public static CommandBindingCollection GetRegisterCommandBindings(UIElement element)
{
return (element != null ? (CommandBindingCollection)element.GetValue(RegisterCommandBindingsProperty) : null);
}
private static void OnRegisterCommandBindingChanged
(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
UIElement element = sender as UIElement;
if (element != null)
{
CommandBindingCollection bindings = e.NewValue as CommandBindingCollection;
if (bindings != null)
{
element.CommandBindings.AddRange(bindings);
}
}
}

This is how you would use it in the view:

<UserControl local:AttachedProperties.
RegisterCommandBindings="Binding CommandBindings}" >

image

Conclusion

There are few other examples of how to do this like Josh Smith posted on CodePlex, but I think this is a much more straightforward approach and requires less code. I really hope this helps someone dealing with the same issue. If you think there is a better way, please let me know.

Code

There is a full example that you can download here. Be sure to change the file extension from .doc to .zip.
kick it on DotNetKicks.com