title: Fat Models, skinny ViewModels and dumb Views, the best MVVM approach?
body: <p>Through generous help on <a href="https://stackoverflow.com/questions/851595">this question</a>, I put together the following MVVM structure which displays the changes of a model in real time in XAML (current date/time), very nice.</p>
  
  <blockquote>
    <p>A cool advantage of this set up is
    that when you look at your view <em>in
    design mode</em> of Visual Studio or
    Blend, <em>you see the time ticking by</em>,
    which means that <em>at design time you
    have access to live data from your
    model.</em></p>
  </blockquote>
  
  <p>In the process of getting this to work, I was surprised to see <strong>most of the bulk move from my ViewModel into my Model</strong>, including implementation of INotifyPropertyChange. Another change is that I <strong>no longer bind to <em>properties</em> on the ViewModel but to <em>methods</em></strong>. </p>
  
  <p>So currently this is my favorite flavor of MVVM:</p>
  
  <ol>
  <li><p>View is dumb: </p>
  
  <ul>
  <li>one ObjectDataProvider for each object you need from your model</li>
  <li>each ObjectDataProvider maps to a method on the ViewModel (not a property)</li>
  <li>no x:Name properties in XAML elements</li>
  </ul></li>
  <li><p>ViewModel is skinny:</p>
  
  <ul>
  <li>the only thing in your ViewModel are the <em>methods</em> to which your view binds</li>
  </ul></li>
  <li><p>Model is fat:</p>
  
  <ul>
  <li>the model implements INotifyPropertyChanged on each of its properties.</li>
  <li>for every method on your ViewModel (e.g. GetCurrentCustomer) there is a corresponding <em>singleton method</em> in your Model (e.g. GetCurrentCustomer).</li>
  <li>the model takes care of any real time threading functionality as in this example</li>
  </ul></li>
  </ol>
  
  <p><strong>Questions:</strong></p>
  
  <ol>
  <li>Those of you who have been implementing MVVM in real scenarios, is this the basic structure you have also settled upon, and if not, how does yours vary?</li>
  <li>How would you extend this to include routed commands and routed events?</li>
  </ol>
  
  <p><em>The following code will work if you just copy the XAML and code behind into a new WPF project.</em></p>
  
  <p><strong>XAML:</strong></p>
  
  <pre><code>&lt;Window x:Class="TestBinding99382.Window1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="clr-namespace:TestBinding99382"
      Title="Window1" Height="300" Width="300"&gt;
  
      &lt;Window.Resources&gt;
          &lt;ObjectDataProvider 
               x:Key="DataSourceCustomer" 
               ObjectType="{x:Type local:ShowCustomerViewModel}" 
                          MethodName="GetCurrentCustomer"/&gt;
      &lt;/Window.Resources&gt;
  
      &lt;DockPanel DataContext="{StaticResource DataSourceCustomer}"&gt;
          &lt;StackPanel DockPanel.Dock="Top" Orientation="Horizontal"&gt;
              &lt;TextBlock Text="{Binding Path=FirstName}"/&gt;
              &lt;TextBlock Text=" "/&gt;
              &lt;TextBlock Text="{Binding Path=LastName}"/&gt;
          &lt;/StackPanel&gt;
          &lt;StackPanel DockPanel.Dock="Top" Orientation="Horizontal"&gt;
              &lt;TextBlock Text="{Binding Path=TimeOfMostRecentActivity}"/&gt;
          &lt;/StackPanel&gt;
  
      &lt;/DockPanel&gt;
  &lt;/Window&gt;
  </code></pre>
  
  <p><strong>Code Behind:</strong></p>
  
  <pre><code>using System.Windows;
  using System.ComponentModel;
  using System;
  using System.Threading;
  
  namespace TestBinding99382
  {
      public partial class Window1 : Window
      {
          public Window1()
          {
              InitializeComponent();
          }
      }
  
      //view model
      public class ShowCustomerViewModel
      {
          public Customer GetCurrentCustomer() {
              return Customer.GetCurrentCustomer();
          }
      }
  
      //model
      public class Customer : INotifyPropertyChanged
      {
          private string _firstName;
          private string _lastName;
          private DateTime _timeOfMostRecentActivity;
          private static Customer _currentCustomer;
          private Timer _timer;
  
          public string FirstName
          {
              get
              {
                  return _firstName;
              }
              set
              {
                  _firstName = value;
                  this.RaisePropertyChanged("FirstName");
              }
          }
  
          public string LastName
          {
              get
              {
                  return _lastName;
              }
              set
              {
                  _lastName = value;
                  this.RaisePropertyChanged("LastName");
              }
          }
  
          public DateTime TimeOfMostRecentActivity
          {
              get
              {
                  return _timeOfMostRecentActivity;
              }
              set
              {
                  _timeOfMostRecentActivity = value;
                  this.RaisePropertyChanged("TimeOfMostRecentActivity");
              }
          }
  
          public Customer()
          {
              _timer = new Timer(UpdateDateTime, null, 0, 1000);
          }
  
          private void UpdateDateTime(object state)
          {
              TimeOfMostRecentActivity = DateTime.Now;
          }
  
          public static Customer GetCurrentCustomer()
          {
              if (_currentCustomer == null)
              {
                  _currentCustomer = new Customer 
                       {  FirstName = "Jim"
                          , LastName = "Smith"
                          , TimeOfMostRecentActivity = DateTime.Now 
                       };
              }
              return _currentCustomer;
          }
  
          //INotifyPropertyChanged implementation
          public event PropertyChangedEventHandler PropertyChanged;
          private void RaisePropertyChanged(string property)
          {
              if (PropertyChanged != null)
              {
                  PropertyChanged(this, new PropertyChangedEventArgs(property));
              }
          }
      }
  }
  </code></pre>