Free!  FoxPro to WPF screen converter
   Almost free!  One day of FREE VFP to WPF evaluation of your FoxPro app ONSITE
   Free!  Read the foreword to Les' new book (available here)...
Skip Navigation Links

Building a ViewModel Base Class

Why write the same code in every ViewModel when you can just inherit it?




Login or register to download source code

Coding time: 20 minutes.   

'

Jump to: 

 Introduction   Building the Test Project  Property Change Notification  Command Binding Conclusion 

 


Introduction

In Article 610 I showed how to implement INotifyPropertyChanged by adding a few lines of code. But the same code has to be added to each ViewModel. Isn't that what inheritance is for?

The same goes for binding the Click event of buttons in the UI to commands in your viewmodel: You have to add the file CommandMap.cs to your project and include a using CommandUtilities statement at the top of in each ViewModel. Can't we do this once and forget about it? Yes we can. All we have to do is create a ViewModelBase class that sports the functionality of these two items, and then inherit from it in all of our viewmodels.


Creating the test project

We'll start by creating a project to test our ViewModel base class. From the menu in Visual Studio 2010, select File, New, WPF Project, and name it ViewModelBase. Add the CommandMap.cs file that we used in Article 610 (already included in the downloadable project). If it's not already included in the project, highlight the filename, right click, and select Include in Project from the context menu. Then, right click on the project name and select Add, New Item, Class, and name the class MainWindow_VM, since MainWindow.xaml is the only form in your project. (As you add forms, you'll usually add one ViewModel for each form.)

Your project will look like this:



Fig. 1: The ViewModelBase testbed project

Once you've built a ViewModel base class that's got everything you could possibly want in it, you can build a dll and just include a reference in your projects. But this is going to be a work in progress for a long, long time, so for the present, plan to include it as a class in your projects.


Property change notification

We'll start by including support for NotifyPropertyChanged. Right click on the project name, and then select Add, Class. Name it ViewModelBaseClass, and add the code shown in Listing 1:


This isn't the only way to implement property change notification in a base ViewModel class. There's a trick that you can use to make it easier to catch refactoring errors involving property names, but I'll leave that for another day. If I wrote everything about everything, this would be a book, not an article.

Now, modify MainWindow_VM.cs so that it contains the code shown Listing 2:


(NOTE: I've actually cheated a bit; I already added the code from CommandMap into my ViewModelBaseClass. So, if you exclude CommandMap.cs from the project, and remove using CommandUtilities from MainWindow.xaml.cs, it will still work.

Next, change MainWindow.xaml to look like Listing 3:


MainWindow.xaml.cs is very, very simple; essentially, we've added four lines of code to the default CodeBehind:

MainWindow.xaml.cs

namespace Framework
{
  public partial class MainWindow : BaseWin
  {
    MainWindow_VM ViewModel;

    public MainWindow()
    { InitializeComponent();
      ViewModel = new MainWindow_VM();
      DataContext = ViewModel;
    }
  }
}

Press F5, and you'll see the first form shown in Fig. 2. Click the button, and its appearance will change to look like the second form:



Fig. 2: Form ready for testing the RaisePropertyChanged event

If you want to see what happens without RaisePropertyChanged in the FontSize setter, for example, change

    private double fontsize = 10;
    public double FontSize
    { get { return fontsize; }
      set { fontsize = value; RaisePropertyChanged("FontSize"); }
    }

to

    public double FontSize { get; set; }

Press F5, and then click on the button: As Fig. 3 shows, this time, the font doesn't resize. It's still a property, and it's still public, but it doesn't implement property change notification, so the View can't see changes.



Fig. 3: Changing a ViewModel property without raising the PropertyChanged event

But now that property change notification is built into all of your ViewModels, it's simple to implement RaisePropertyChange on any property whose values might change and need to be displayed in the View. One more problem solved with inheritance.


Command Binding

What about commanding? Can we take the technique that was used in Article 610 to bind a ViewModel method to the Click event of a button in a View and add it to our ViewModelBase class? Yuuup! In fact, I already did. I just didn't show you how I did it.

In my previous article, we saw that commanding required adding a file called CommandMap.cs and adding using CommandUtilities (the NameSpace declared in CommandMap.cs) to the top of the ViewModel code. If we simply include the CommandMap code in ViewModelBase.cs, the using CommandUtilities statement in each ViewModel is no longer necessary. I removed a boatload of comment and blank lines, and squeezed 240 lines down to 80 before adding them to ModelViewBase. The resulting ViewModelBase class is shown below in Listing 4:


As you saw earlier, you have to initialize the _commands collection in the ViewModel's constructor:

   _commands = new CommandMap();

Then, for each button that has a Click event, add the command:

   _commands.AddCommand("ChangeLabel", x => Change_Label());

and, of course, write the method added using AddCommand:

   public void Change_Label()
   {
     LabelText = "Well, did it?";
     ColorName = "Red";
     FontSize = 24;
   }

Then, in the xaml for the corresponding button in your View, bind the command:

     Command="{Binding Commands.ChangeLabel}"

Now, to prove that we no longer need CommandMap.cs, exclude it from the project, remove the using CommandUtilities from the top of MainWindow_VM, and rebuild the project. Click on the button, and you'll see the first form shown in Fig. 4. Click on the button, and the second form in Fig. 4 will appear:



Fig. 4: Obviously, the command binding worked

So there you have it. Your viewmodels now support property change notification and command binding right out of the box.

Where to go from here

There is a ViewModel base class written by Brian Genisio that you can download as a dll and use in your projects. (NOTE: You can also compile this project as a dll and add it as a reference in your other WPF projects.) Brian's ViewModelBase class has more features, but it uses Dynamic Properties, which is a little advanced for an introductory article like this one. Start with this one and add features as you become comfortable wth them.


Conclusion

In this article, we've taken the first steps toward building a base class for your ViewModels. As you see the need to add more features, rather than adding them to each ViewModel, put them in your ViewModel base class. Your base class will evolve, and all of your ViewModels will benefit from its evolution.

See 'ya :)

qqq


Copyright(C) Pinter Consulting, 2012Tel: +1 (650) 464-6924
Automated conversion between C# and VB by Visible C#/Visible VB from Tangible Software Solutions