Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
UI Patterns for WPF

There’s a lot of recent buzz about the Model-View-ViewModel or MVVM. (I pronounce it like it rhymes with Auntie Em.) Rather timely for me as a lot of my thinking about implementing UI patterns in WPF has begun to coalesce.

There’s has been a lot of thought given to UI patterns prior to the advent of WPF. Martin Fowler has a relatively succinct historical overview of GUI architectures. I’d like to start here by discussing how these established patterns are mapped to WPF. After that, I’d like to explore how WPF allows us to improve on these patterns. We’re probably in for a series of posts here.

Why Patterns?

One guiding principle, both for testability’s sake as well as for myriad other reasons, is Separated Presentation. This is a just a special case of the general principle Separation of Concerns. We separate the concerns because they are easier to test, maintain, and extend.

Let’s assume that you buy into the value of testability. The next problem is that UI code is notoriously difficult to test. This is a product of the way UI frameworks generally work. The common solution is to push as much behavior as possible into Plain Old CLR Objects (POCO). In other words, if a class is tied to the UI framework, and thus is difficult to test, it should have as little logic in it as possible; instead that logic should be delegated to classes that are easier to test.

The Patterns

There are number of standard approaches, er, patterns, that have been recognized. My influences for interpreting  these patterns are Martin Fowler, Jeremy Miller, John Gossman, and Dan Crevier.

An example of the registration formI want to show you have these patterns look in code, so let’s establish a quick (and highly contrived) scenario. We have a registration form that accepts an email address, a password, and a confirmation of the password. There’s a button to initiate the registration, but the form has to be in a valid state in order for the button to be enabled. The rules are:

  • The email address cannot be blank.
  • The password cannot be blank.
  • The confirmation must match the password.

Now for the patterns…

The Autonomous View

This is what we don’t want to do, but usually do. All of the logic is in the code-behind. Very little is delegated out to other classes, and when it is, it is typically delegated to concrete types so that hard dependencies exist. It’s impossible to test with this pattern because it is impossible to isolate the behavior that need to be tested. Here’s the xaml and the code-behind.

Model-View-Presenter

I’ve used the term MVP a lot. (Hey, I am one now!) Fowler has suggested that MVP subsumes two more specific patterns (and that the term MVP should be retired in favor of them). Both of the child patterns have the same elements: a model, a view, and a presenter. Generally, the model is data that you are interested in, the view renders the data on screen, and the presenter handles all the “presentation concerns”. What constitutes “presentation concerns” though is part of what distinguishes the two child patterns.

Supervising Controller

The first of the MVP patterns is the supervising controller, or supervising presenter. (The terms controller and presenter are somewhat ambiguous themselves and are frequently interchanged.) The  presenter in the supervising presenter pattern has properties that interact with the view through data binding. Frequently, you’ll have simple event handlers (e.g., the click event for a button) that merely call methods on the presenter. (There is an alternative to the event handlers, but I’ll get to that later.)

This pattern is easy to test because the presenter has most of the behavior for the UI and it is POCO. The deficit is that the view still contains some logic in the form of bindings.

Notice here that we’ve introduced bindings into the xaml and that there is almost nothing in the code-behind. The real behavior is here in the presenter.

Passive View

This flavor of MVP squeezes out the remaining behavior out of the view. With this pattern you define an interface for the view that the presenter operates against. The implementation of the view interface has to be very simple, you want the absolute bare minimum in the view. The view is passive because it doesn’t know or do anything. The presenter handles all of the logic and manipulates the view. In WPF, you’ll end up with more code in the code-behind (because you are implementing the interface), but you can avoid bindings. Why do you want to avoid bindings? Because they are harder to tests… or are they? More on that later.

Here’s the view’s interface. Note that the code-behind is more involved, but the xaml no longer has bindings. Also, notice how the presenter has to know a lot more about the view.

A Warning

We all want patterns to be distinct and specific, but the reality is that they are blurry. Often you will be combining elements from various patterns in order to accomplish what you need to do. Don’t get hung up on implementing a pure pattern.

Presentation Model vs MVVM

Actually, I will pick up here next time. I need to give you a reason to come back, right? :-)

If you are interested in the playing with the code examples, I’m posting it on CodePlex.


Posted 01-19-2009 10:19 PM by Christopher Bennage

[Advertisement]

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)