WPF and Silverlight design patterns

In this post I’ll describe the design patterns which are used in large and complex applications in order to simplify their development and maintenance.

Model View ViewModel
Separates Model and View by introducing the intermediate layer which is called ViewModel. It is a some kind of a “super converter” which adds additional properties and behavior to the model. Also commonly used as a replacement of code-behind.
The most common features of ViewModel:

  • Property changes notification with the INotifyPropertyChanged interface
  • Validation with the IDataErrorInfo or INotifyDateErrorInfo interfaces
  • Event handling of View events
  • Invocation of WCF services
  • Converting of model properties from one data type to another

Example of Model and ViewModel:

public class UserModel
{
	public string Name { get; set; }
}

public class UserViewModel : IDataErrorInfo, INotifyPropertyChanged
{
	private string name;

	public string Name
	{
		get { return name; }
		set
		{
			name = value;
			RaisePropertyChanged("Name");
		}
	}

	public ICommand ChangeNameCommand { get; set; }

	public string Error
	{
		get { throw new NotImplementedException(); }
	}

	public string this[string columnName]
	{
		get { return this._validator.GetErrors(columnName).FirstOrDefault(); }
	}

	public event PropertyChangedEventHandler PropertyChanged;

	private void RaisePropertyChanged(string propertyName)
	{
		if (this.PropertyChanged != null)
			this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
	}
}

Links:
Wikipedia. Model View ViewModel
Developer’s Guide to Microsoft Prism. Implementing the MVVM Pattern
Never In Doubt: MVVM Backlash

 

Dependency Injection
The purpose of this pattern is to get rid of using of external classes and to use interfaces instead.
This pattern adds the following benefits:

  • Allows to write unit tests because interfaces can be replaced by “fake” classes
  • Allows to change one interface implementation by another without affecting or changing existing objects

For example, this class:

public class MyViewModel
{
	public MyViewModel()
	{
		this.SomeProperty = Resources.String1; // the static class call
	}

	public void Refresh()
	{
		var model = new MyWcfServiceClient().GetModelById(this.Id); // the service creation

        // initialize the corresponding properties of the view model
	}
}

should be rewritten so:

public class MyViewModel
{
	public MyViewModel(IResourceManager resourceManager, IServiceClient serviceClient)
	{
		this._resourceManager = resourceManager;
		this._serviceClient =  serviceClient;

		this.SomeProperty = this._resourceManager.String1;
	}

	public void Refresh()
	{
		var model = this._serviceClient.GetModelById(this.Id);

        // initialize the corresponding properties of the view model
	}
}

Links:
Wikipedia. Dependency injection
MSDN Magazine. Design Patterns: Dependency Injection

 

Modular Application
This concept is based on the logical division of application components and if you use several projects with different functionality, you already use a some kind of modules. For example, if your solution has projects like Application.Mail, Application.Calendar, Application.Tasks – it has 3 modules as well.

Besides the above mentioned logical division, the Prism framework adds the following features:

  • Allows to add modules after the application is released (some kind of plug-ins)
  • Allows to defer module loading and load some of them on demand

Links:
Developer’s Guide to Microsoft Prism. Modular Application Development

 

Event Aggregator
This pattern is known as Messenger in the MVVM Light Toolkit. Implements the “publish-subscribe” model. For example, if one view model should call a method of another view model, it can be done by using two ways:
1. Bad practice: The first view model gets the second view model as the constructor parameter and then calls the necessary methods directly by using the code like this._otherModel.OnUserUpdated(this).
2. The preferred approach: The second view model publishes an event, the first one subscribes to it and handles appropriately.

Links:
Martin Fowler. Event Aggregator
Developer’s Guide to Microsoft Prism. Communicating Between Loosely Coupled Components

 

Command
Allows to get rid of the code-behind and handle button clicks inside a view model. Also it is useful when the same action is invoked from the application menu, context menu, toolbar and buttons, so you don’t need to write separate event handlers and you can use just a single command everywhere.
Besides the method invocation, commands in WPF affects the IsEnabled property of buttons and menu items as well: if a command can’t be executed, all the invoke buttons will be disabled.

Links:
Wikipedia. Command pattern
MSDN. Commanding QuickStart

About these ads

5 Responses to WPF and Silverlight design patterns

  1. Your first example doesn’t make any sense. If UserViewModel has every field that UserModel has, then there is absolutely no reason for UserModel to exist. (Well unless you are billing by the hour and like writing adapter code.)

    Your second example doesn’t match your first. It has a _model field, that doesn’t exist anywhere in your first example.

    Take another look at the MyViewModel example in the Prism 4 article. It doesn’t wrap the model properties; rather it holds a collection of them. This allows you to unit test the logic of the models (business rules, validation, etc.) without having to muck about with mocking up a service layer.

    • vortexwolf says:

      Actually there is nothing wrong that the view model has the same properties that the model has. Moreover, in large projects there are several model layers: PersistenceModel (related to the database), DomainModel (related to the domain logic), and PresentationModel (related to the UI), with only one purpose to separate the project into layers. A service can’t return the view model, so the model must exist anyway.

      My second example shouldn’t have anything to do with the first one, In any way I’ll correct the code and write explicit comments.

      About the Prism 4 article, I suppose it is called “Chapter 5: Implementing the MVVM Pattern”, the MyViewModel implementation isn’t good there because that class can’t be easily resolved by the IoC container. It is much better when the constructor of a class contains only interfaces. Also I would map the collection of the Customer type to the collection of the CustomerViewModel class even if they didn’t have differences at all (the AutoMapper library can handle this case easily).

    • vortexwolf says:

      Ok, I’ve found 4 reasons why the view model class should always be created regardless of similarity to the model class: http://vortexwolf.wordpress.com/2011/11/29/the-necessity-of-a-viewmodel-class-for-each-model-class/ . Also I’ve proven that it doesn’t take much time to create an extra class, especially because that class will save much more time in the future.

  2. Anonymous says:

    The pattern you are using is known as “foms over data”. We’ve used it successfully for decades in .NET and classic VB before it.

    MVVM is something different. The whole point is to separate the data stored in the model from the external services (e.g. database, web services) that act upon it.

    You don’t have to use MVVM if you don’t want to. There are perfectly good ways to write code without it. But you really should make a decision. Mindlessly creating “view-models” that do nothing but minic your model objects gives you nothing.

    • vortexwolf says:

      Google says that “form over data” is when a database model is bound directly to a view, whereas in my case I create the intermediate layer.
      You must have confused this concept with something else, with the “excessive complexity” antipattern, I guess. But I would rather say that it is “Anti corruption layer”.

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

Follow

Get every new post delivered to your Inbox.

Join 25 other followers

%d bloggers like this: