WPF : MVVM VS Project Template

This weekend I was going to finally write up all my pains and worries and problems solved in a neat MVVM mini framework, and was really looking forward to it, and then I opened my email, and there was one from Lester. It seems that Microsoft have finally created a Visual Studio template to get you up to speed when creating WPF MVVM apps. Read more about it over at Lesters Blog : http://blogs.msdn.com/llobo/archive/2009/05/01/download-m-v-vm-project-template-toolkit.aspx

I have tried this out, and if you are just getting to grips with the MVVM pattern there are a couple of good features in there, such as the overall project structure that is created, I think this is good. Here is what you get

Structure

I also like the fact that the ICommand implementation (DelegateCommand) uses WeakReferences.

   1:  #region ICommand Members
   2:   
   3:  /// <summary>
   4:  ///     ICommand.CanExecuteChanged implementation
   5:  /// </summary>
   6:  public event EventHandler CanExecuteChanged
   7:  {
   8:      add
   9:      {
  10:          if (!_isAutomaticRequeryDisabled)
  11:          {
  12:              CommandManager.RequerySuggested += value;
  13:          }
  14:          CommandManagerHelper.AddWeakReferenceHandler(
  15:              ref _canExecuteChangedHandlers, value, 2);
  16:      }
  17:      remove
  18:      {
  19:          if (!_isAutomaticRequeryDisabled)
  20:          {
  21:              CommandManager.RequerySuggested -= value;
  22:          }
  23:          CommandManagerHelper.RemoveWeakReferenceHandler(
  24:              _canExecuteChangedHandlers, value);
  25:      }
  26:  }
  27:   
  28:  bool ICommand.CanExecute(object parameter)
  29:  {
  30:      return CanExecute();
  31:  }
  32:   
  33:  void ICommand.Execute(object parameter)
  34:  {
  35:      Execute();
  36:  }
  37:   
  38:  #endregion

Notice the CommandManagerHelper class which looks like:

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

   1:  /// <summary>
   2:  ///     This class contains methods for the CommandManager that help avoid 
   3:  ///    memory leaks by using weak references.
   4:  /// </summary>
   5:  internal class CommandManagerHelper
   6:  {
   7:      internal static void CallWeakReferenceHandlers(List<WeakReference> handlers)
   8:      {
   9:          if (handlers != null)
  10:          {
  11:              // Take a snapshot of the handlers before we call out to them since the handlers
  12:              // could cause the array to me modified while we are reading it.
  13:   
  14:              EventHandler[] callees = new EventHandler[handlers.Count];
  15:              int count = 0;
  16:   
  17:              for (int i = handlers.Count - 1; i >= 0; i--)
  18:              {
  19:                  WeakReference reference = handlers[i];
  20:                  EventHandler handler = reference.Target as EventHandler;
  21:                  if (handler == null)
  22:                  {
  23:                      // Clean up old handlers that have been collected
  24:                      handlers.RemoveAt(i);
  25:                  }
  26:                  else
  27:                  {
  28:                      callees[count] = handler;
  29:                      count++;
  30:                  }
  31:              }
  32:   
  33:              // Call the handlers that we snapshotted
  34:              for (int i = 0; i < count; i++)
  35:              {
  36:                  EventHandler handler = callees[i];
  37:                  handler(null, EventArgs.Empty);
  38:              }
  39:          }
  40:      }
  41:   
  42:      internal static void AddHandlersToRequerySuggested(
  43:         List<WeakReference> handlers)
  44:      {
  45:          if (handlers != null)
  46:          {
  47:              foreach (WeakReference handlerRef in handlers)
  48:              {
  49:                  EventHandler handler = handlerRef.Target as EventHandler;
  50:                  if (handler != null)
  51:                  {
  52:                      CommandManager.RequerySuggested += handler;
  53:                  }
  54:              }
  55:          }
  56:      }
  57:   
  58:      internal static void RemoveHandlersFromRequerySuggested(
  59:         List<WeakReference> handlers)
  60:      {
  61:          if (handlers != null)
  62:          {
  63:              foreach (WeakReference handlerRef in handlers)
  64:              {
  65:                  EventHandler handler = handlerRef.Target as EventHandler;
  66:                  if (handler != null)
  67:                  {
  68:                      CommandManager.RequerySuggested -= handler;
  69:                  }
  70:              }
  71:          }
  72:      }
  73:   
  74:      internal static void AddWeakReferenceHandler(
  75:        ref List<WeakReference> handlers, EventHandler handler)
  76:      {
  77:          AddWeakReferenceHandler(ref handlers, handler, -1);
  78:      }
  79:   
  80:      internal static void AddWeakReferenceHandler(
  81:        ref List<WeakReference> handlers, EventHandler handler, 
  82:        int defaultListSize)
  83:      {
  84:          if (handlers == null)
  85:          {
  86:              handlers = (defaultListSize > 0 ? new 
                   List<WeakReference>(defaultListSize) : new List<WeakReference>());
  87:          }
  88:   
  89:          handlers.Add(new WeakReference(handler));
  90:      }
  91:   
  92:      internal static void RemoveWeakReferenceHandler(
  93:        List<WeakReference> handlers, EventHandler handler)
  94:      {
  95:          if (handlers != null)
  96:          {
  97:              for (int i = handlers.Count - 1; i >= 0; i--)
  98:              {
  99:                  WeakReference reference = handlers[i];
 100:                  EventHandler existingHandler = reference.Target as EventHandler;
 101:                  if ((existingHandler == null) || (existingHandler == handler))
 102:                  {
 103:                      // Clean up old handlers that have been collected
 104:                      // in addition to the handler that is to be removed.
 105:                      handlers.RemoveAt(i);
 106:                  }
 107:              }
 108:          }
 109:      }
 110:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

I think I could be tempted to use this from now on. And one more thing I like is the CommandReference class which allows a Key to be associated with an ICommand in XAML like

   1:  <Window x:Class="WpfModelViewApplication1.Views.MainView"
   2:      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:      xmlns:c="clr-namespace:WpfModelViewApplication1.Commands"
   5:      Title="Main Window" Height="400" Width="800">
   6:      
   7:      <Window.Resources>
   8:          <!-- Allows a KeyBinding to be associated with a 
   9:          command defined in the View Model  -->
  10:          <c:CommandReference x:Key="ExitCommandReference" 
  11:                              Command="{Binding ExitCommand}" />
  12:      </Window.Resources>
  13:     
  14:      <Window.InputBindings>
  15:          <KeyBinding Key="X" Modifiers="Control" 
  16:                      Command="{StaticResource ExitCommandReference}" /> 
  17:      </Window.InputBindings>
  18:      
  19:      <DockPanel>
  20:          <Menu DockPanel.Dock="Top">
  21:              <MenuItem Header="_File">
  22:                  <MenuItem Command="{Binding ExitCommand}" Header="E_xit" 
  23:                            InputGestureText="Ctrl-X" />
  24:              </MenuItem>
  25:          </Menu>
  26:      
  27:          <Grid>
  28:              <!-- Add additional content here -->
  29:          </Grid>
  30:      </DockPanel>
  31:  </Window>

But as for the rest, it is nothing that the WPF Disciples have not been doing for ages. What I am really disappointed by, is the lack of thought about services such : OpenFile/MessageBox/OpenDialog etc etc.

These are very very important, and far harder to get right that the basics.

In closing, I would say this is a step in the right direction, but some work still needs to be done to bridge the gap. I am not saying a full blown CAL/Prism template is required, but thought needs to be given to services. This is what is most likely to trips newbie WPFers up, I mean I have been working with WPF a while now, and I only just get it. What hope has a newbie got.

Looks like I will be writing my stuff up after all. Yipee

Advertisements

13 thoughts on “WPF : MVVM VS Project Template

  1. tawani says:

    You know Saacha, I actually came immediately to your site to see if anybody had commented on the lack of UI services (OpenFile/MessageBox/OpenDialog etc etc.).

    It is a great simple framework for starters, but I still think they should have added a simple “MessageBox” to the example.

  2. Marlon Grech says:

    did u really like it??? for me it has nothing in their but the DelegateCOmmand… something that has been in the community ages ago…

    am I missing something??

  3. sacha says:

    Tawani

    Yeah they missed a trick for sure. Ill be working on my own framework very soon. I find their lack of faith in services disturbing

    PS :
    I will be writing a book soon, which would be cool I hope.

  4. sacha says:

    Marlon

    This template has nothing for dudes like you, but for absolute beginners, I can its benefit, at least a firm structure and good base point is created.

  5. Templeton says:

    Hi Sacha,
    I’m a new reader of your blog. I started using WPF some months ago and I have a dude with WPF. I was searching your e-mail but didn’t find it 😦

    I wanna show objects in a Window.
    I have some objects and I created datatemplates for them. To show the objects I create labels and instance the objects into its content.
    ¿Is it a good practice? ¿Is there a better solution?

    ¡Thanks!

  6. sacha says:

    Templeton,

    I do not understand what you are asking. But I have to say I do not have time to field open ended questions like this, if a question is raised against a blog/article I always try to answer it, but I do not have time to help everyone.

  7. Gites France says:

    The template works well for me. Thanks – I appreciate what you are doing.

  8. sacha says:

    Gites

    I think that template is just ok to be honest. You could check out my Cinch MVVM framework for a fuller MVVM implemented library.

    http://sachabarber.net/?p=522

  9. Hasan Jaffal says:

    Introduction About MVVM – Model View ViewModel Design Pattern
    By SA
    Last week was my first presentation while playing the Solution Architect Role in ArabiaGIS, so I tried to start with an introduction to design patterns, and my first subject was the Model-View-ViewModel design pattern. in the presentation I tried to introduce the design pattern concept, showing its importance and the goals off applying it.

    The presentation will focus on the history and the importance of MVVM and then go into the detailed of this important design pattern for architecting a WPF application.

    To see the presentation: http://solutionsarchitecture.wordpress.com/2009/11/13/introduction-about-mvvm-model-view-viewmodel-design-pattern/

  10. Tina says:

    How is Cinch differed from Josh Smith MVVM library? just curious because I haven’t read either one.

    • sacha says:

      Joshs is very light weight, and offers a few things like INotifyPropertyChanged (INPC), PropertyObserver, RelayCommand and Mediator. Cinch offers all this and many more things, such as threading helpers, attached behaviours and IOC services and test services as well. Better INPC property generators using expression trees, and also DataWrappers to allow VM to control every bit of editable datas state

      Oh and CInch has good documentation and a code generator.

  11. Edison says:

    Hi sacha, I am your big fan back here in Africa. I have read a couple of your write up on WPF in codeproject.com and they have being very helpful as a beginner. Please, I have being finding it very hard to grab MVVM concept. The whole thing is confusing to me. Can you help me. Thanks

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: