In part one we looked at the concept of a presentation model. In this post we are going to going to start putting together some crude code to scaffold out our presentation model base classes. This article should give you the basic idea how things are related, and what purpose they serve. There are really 3 core classes I use to provide the foundation for my implementation of a Presentation Model Pattern: (1) PresentationModel, (2) ObservableModelCollection, and (3) ObservableModel. If you think about the data on your screen, you are probably going to have a root data object (your presentation model), but you are also going to have to represent items in a data grid, charting data, etc. All these items require that you have a collection (actually an ObservableModelCollection) of “sub-models” (ObservableModel).
We’ll tackle ObservableModel first since it’s the root of our implementation. ObservableModel provides a base class which actual models can inherit to automatically get notification of changes to the data in the model. ObservableModel does this by supporting the INotifyPropertyChanged interface which WPF knows to listen to for the PropertyChanged event.
This is the same interface that DependencyObject implements, so some might ask “Why don’t we build ObservableModel on DependencyObject?” Well, it turns out I thought about this. My first attempt at a PM implementation was based off of DependencyObject (DO from now on), but I quickly found out that some of the more advanced services I wanted to offer were difficult to implement because DO abstracted so much away from me. One of the best examples of this was Undo/Redo. To implement this, I really wanted to control how property values were stored, but DO hides this from inheritors. I didn’t want to completely hijack DO, so I eventually resolved to create my own set of classes.
Implementing INotifyPropertyChanged requires that we raise an event whenever a property changes on an object inherited from OM, but how do we know when a property changes? We don’t really want our inheritors having to raise the event explicitly in every property setter, so we’ll do the same thing DO does, we’ll implement GetValue and SetValue methods.
That’s about all we need right now. While there are a lot of interfaces we will eventually add to our ObservableModel class, we’ll just implement INotifyPropertyChanged for now.
Now that we have the basics down, let’s create PresentationModel. Our PresentationModel class needs the same features as ObservableModel, fortunately we thought about this ahead of time, and we are just going to inherit PresentationModel from ObservableModel. We need to add a few more things to PresentationModel though. First off, we want to be able to initialize our PM with data. We could do that in the constructor, but there is a better option: ISupportsInitialize. While there are two methods to control initialization on this interface, we are going to abstract those from our inheritors, and create an abstract method called Initialize(). This is where our inheritors are going to begin getting data for their screen.
We also need one more thing: CommandBindings. In order for our PM to accept commands from the View, we need to have some way for the View to figure out which commands we support and send us those commands. To do this, we’ll create a CommandBindings property which will be filled up by our inheritors. The View will add this to the Page’s CommandBindings property so commands are automatically forwarded to us from WPF.
Now we have the basics setup. For good measure we are also going to create ObservableModelCollection. Why can’t we just use ObservableCollection? Well for one, there are a bunch of UI Controls (Infragistics in particular) which don’t do a good job of listening to events on sub-models, so we want our ObservableModelCollection to listen to those events and forward some of them up. Secondly, we are going to need this when we eventually implement Undo/Redo. ObservableCollection is a good start though, so we’ll use this as our base class and add the event forwarding.
That’s all for now, in part 3 we’ll create a model/view pair which uses these base classes.