The Humble Dialog Box [pdf] is a pattern to separate UI behavior from code that deals with a specific view technology, like WPF. Essentially, for each window you have a UI data/behavior class, an abstract view class (or interface), and a concrete view for each different type of view you're supporting. The view class should have all view technology specific code and almost nothing else. Everything else should be routed to the behavior class.

Each concrete view is responsible for rendering the information in the behavior class on demand and routing all inputs (keyboard, mouse, etc) to it. The behavior class has no public getters, so it's hard for the view to handle most events itself anyway. Model View Presenter from Fowler's Patterns of Enterprise Application Architecture is essentially the same thing, and has a simple C# example.

The simple steps (from the end of the Humble Dialog Box article) are:
  1. Create a class for the smart object, and an interface class for the view. Pass the view to the smart object
  2. Develop commands against the smart object, test first. Write your tests against a mock view.
  3. Create your dialog class and implement the view interface on it. Gestures on the dialog should delegate to commands on the smart object. Calls from the smart object to the dialog should resolve to simple setter methods.
One obvious reason to do this is to support different views that have the same underlying behavior (perhaps differing only in layout). The reason I usually use it is to support a mock view to use in unit testing.

This is not the same as the separation of behavior that you get with the XAML file and the code-behind (.xaml.cs) file, because the code file will still usually have some WPF specific code in it. That's ok, but it's not Humble Dialog Box. To get that you'd need to add an abstract superclass or interface to the code-behind file and a behavior class that you route all events to.

The interesting cases are how you handle simple events in the view without routing them through the behavior class. For instance, if you have a list box on your window, you wouldn't want to route the mouse click on an item back to the behavior class so that it could change the selected item. Usually, you let the list box handle the mouse click and then route a selection changed event if needed. If the views don't dynamically change with the list box selection, you can just send the selection to the behavior class when the OK button is clicked.

Sometimes the Humble Dialog Box is overkill, but if you have complex UI behavior that you want to unit test, it's pretty useful. It is with unit testing in mind that I want to explore some of the XAML features that deal with UI behavior, namely Triggers, Data Binding, and Animation.

Triggers allow you to put simple event handlers right in your XAML. Here's a simple example that changes a button's background to yellow when the mouse is over them.

      <Style TargetType="{x:Type Button}">
        <Style.Triggers>
          <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Background" Value="Yellow"/>
          </Trigger>
        </Style.Triggers>
      </Style>

Triggers are great for these simple single-control behaviors, especially if they have no impact on the data model. If they get much more complex than this, then it will be hard to unit test. Also, if the behavior needs to be supported for non-XAML views, then it would be better to handle it outside of XAML. Any trigger that affects controls other than the one with the trigger is definitely suspect -- I'm not even sure how you do that, since the setters don't take an object anyway, but even if you can, I would stay away from that.

Data Binding lets you automatically route events to a model object and propagate changes back to the view (by binding controls to events in the model). They are very close to the Humble Dialog, and perhaps good enough for most cases. The model classes are certainly testable, but in the simplest implementations, you will still handle the event in the XAML code-behind class and then call setters on the model object.

To be more like the Humble Dialog, the event handlers should just send the event to the model objects, which then calls setters on itself (raising PropertyChanged events to get the changes back to the view). Code in the xaml.cs file should refrain from calling the getters in the model class and operating on the results -- let the model's events tell you when to update.

Animation is a complex enough behavior to want to unit test. However, the alternative to using XAML is not pretty, and the sheer amount of code savings and simplification you get by using XAML might outweigh the benefits you'd get from controlling animation outside of XAML in another class. My approach to unit testing animation would be to read the XAML into a test class and make some assertions on its structure (for instance to check coordinated timings).

My first impression with WPF and XAML is that I would want to take advantage of its features, even if that meant making my UI's less testable--simplification is less error-prone, and code I don't need to write also doesn't need to be tested.

Data Binding certainly supports unit testing of the model classes and it's easy to get to Humble Dialog from it. Animation and Triggers can be somewhat tested by asserting the contents of the XAML file. I will blog more as I explore these methods.