Archive for January, 2008

A New Software Architecture Pattern: M-V-poo

Wednesday, January 23rd, 2008

I just saw a *GREAT* presentation by Josh Smith on using the Model View Controller (MVC) pattern to develop WPF applications.  Josh did an awesome job of breaking down the different pieces of the pattern into understandable parts and showing how each fits into a very simple WPF application.  And of course, he’s already blogged about it

UPDATE:  1/28/08

Josh just posted this excellent Code Project article explaining his approach to MVC and unit testing in WPF.  It is a written version of the WPF Bootcamp presentation that he delivered at Microsoft last week.

The live presentation will eventually be available online in either streaming media or downloadable format and I will update this post with a link.

Those of us who have been writing WPF software for a while have (either consciously or subconsciously) moved to a similar architecture for our applications.  Such an architecture allows us to better leverage the power of the platform to separate UI design from the logic that is used to manipulate (or control) a view of the data.  There are many different variations of the pattern, including M-V-P (and variants), M-V-VM, or my version, which I’m choosing to call M-V-poo.

Every discussion I’ve seen on these software architecture patterns eventually ends with an argument amongst the purists as to whether specific functionality belongs in the controller (a.k.a., the presenter, the view model, the whatever); or whether the controller should really be allowed to reach into the view; or whether the controller should have any dependencies on a specific UI technology; or ad infinitum.

I anticipate seeing similar debates regarding Josh’s example.  My favorite part of the talk was where he gave a nod to the purists and invited them to share such feelings with the caveat that he just doesn’t care.  😀

We all recognize that in a perfect world, there would be a clear delineation of boundaries… but unfortunately we write software in the real world.  The cold hard fact is that there are definitely aspects of WPF (especially around things like commanding) that make it impractical to completely separate the presenter from the view.  The same thing can be said about every other UI platform I’ve seen thus far.  But WPF definitely gets us a lot closer to a perfect world than prior Windows technologies.

This leads me to my new pattern:  M-V-poo (because really, there just aren’t enough architecture patterns! ;)).  My pattern acknowledges that there may indeed be “poo” within the view model, but it tries to minimize that poo (or at least make it less stinky) whenever possible.  Please feel free to use this pattern royalty free!

Reflect On This

Wednesday, January 16th, 2008

In a blatant attempt to put Lutz Roeder out of business (or at the very least, hasten the demise of his empire), today Microsoft released the source code for a number of .NET technologies, including Windows Presentation Foundation.  Seven Attorneys General have already vowed to investigate this act as a possible violation of the consent decree.  Read more here.

EDIT: 1/18/08

That’s right… I did it!  I renamed this post and removed the ‘M’ word.

Why?  Because I do not want anyone to mistakenly associate me with these dolts (thanks for the tip, Brownie) who are addlepated enough to *actually believe* that this move by Microsoft represents monopolistic behavior.  They don’t get it!  The source code was not released for their benefit, nor was it released to injure them…  It was released to help those of us who are actually writing Windows software.  It certainly has nothing to do with their little project to reinvent someone else’s IP.

“Idiots!” 

          – Napoleon Dynamite

Worth the wait… this app KaRocks!

Tuesday, January 8th, 2008

When answering WPF questions, I like to provide pure markup samples, whenever possible.  I’m going to divulge a little secret now…  Whenever I post such a "XamlPad-ready" sample, there’s a 98% chance that I’ve never actually tested it in XamlPad.  That’s because I’ve been a kaxaml user since the 0.1 alpha release.

I’ve always liked kaxaml because of its "snippets" feature, but now there are many new reasons to really love this software.  (I’m not just saying this because Robby likes my snippets, either!)  Seriously, check it out!

(Ahhh… finally, I can cut and paste code directly from kaxaml into my forum posts… no more interim step of pasting into VS to get the syntax coloring!  And intellisense too!  Life is good. :D)

ItemsControl: 'D' is for DataTemplate

Thursday, January 3rd, 2008

The term “rich content model” is sometimes thrown around in WPF circles. In this post, we examine this content model, especially as it pertains to items controls.

The WPF Content Model

In WPF, different classes of elements are categorized based on the type and number of their logical children. We also refer to these logical children as the “content” of the control. WPF defines several different “content models” for various different classes of elements.

The controls that can contain a single item (single logical child of type Object) are called “content controls”. These controls derive from the ContentControl base class. Controls that can contain a collection of items (many logical children of type Object) are called “items controls”. These controls derive from the ItemsControl base class. (These are the controls that we are focusing on in this ItemsControl series, so I’ll come back to them shortly…)

If you took time to explore the different items controls at the end of The ICIQ Test, you know that there are also controls that contain a single header item plus a collection of content items. These controls are called “headered items controls” and derive from the HeaderedItemsControl base class. Similarly, there are controls that contain a single header item plus a single content item called “headered content controls” (which, of course, derive from the HeaderedContentControl base class).

Just to be complete, I should note that there are several other types of elements that have their own content models. For example, a TextBlock can contain a collection of Inline items, which are text elements that derive from the Inline base class and are used to create flowing, formatted text. A Decorator is an adorning element that can contain a single child of type UIElement. A Panel is a layout element that contains a collection of UIElement items and is responsible for sizing and positioning those children.

The ItemsControl Content Model

So what’s so special about the content model of ItemsControl? Primarily, it allows the logical children of an ItemsControl to be any CLR objects. This is fairly remarkable, if you think about it. Traditionally, Windows developers have built up user interfaces by composing visual elements like buttons, labels, combo boxes, text boxes, etc. But using WPF’s rich content model (especially as it applies to the ContentControl and ItemsControl classes), it is now possible to build up a logical UI composed of both visual elements and data items.

To better understand this, consider the following simple example:

<Window x:Class="HomersListBox.Window1"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:src="clr-namespace:HomersListBox"
    Title="Homer's ListBox" Width="300" Height="400">
  <ListBox Width="200" Height="300">
    <src:Character First="Bart" Last="Simpson" Age="10"
        Gender="Male" Image="images/bart.png" />
    <src:Character First="Homer" Last="Simpson" Age="38"
        Gender="Male" Image="images/homer.png" />
    <src:Character First="Lisa" Last="Simpson" Age="8"
        Gender="Female" Image="images/lisa.png" />
    <src:Character First="Maggie" Last="Simpson" Age="0"
        Gender="Female" Image="images/maggie.png" />
    <src:Character First="Marge" Last="Simpson" Age="38"
        Gender="Female" Image="images/marge.png" />
  </ListBox>
</Window>

In this example, the logical tree looks like this:

The Character object is a very simple CLR object with properties that identify characteristics of a cartoon character, such as strings to represent a first and last name, an int value to represent an age (normally, a person’s age would be represented by a calculation performed on their date of birth, but most cartoon characters never actually age :)), an enum value to represent a gender, and a string value that indicates a path to an image of the character.

When you run this little sample, you see the window shown here.

As you can see, the visual representation of the Character object is just a string. If WPF does not know how to visually represent an object, it merely calls the ToString() method of the object to get a semi-meaningful textual representation of the item.

If you were to examine the element tree of the above sample using Snoop or Mole, you would see that WPF has conveniently inserted a TextBlock into the visual tree to display the string representation of the Character. (Note that the TextBlock is part of the visual tree of elements, but it is not a member of the logical tree. The visual tree consists solely of visual elements, whereas, the logical tree may consist of both visual and non-visual objects.)

This automatic TextBlock creation is the framework’s default behavior whenever it needs to display string content within a ContentControl. In this example, the ContentControl is a ListBoxItem (the item container for a ListBox).

In scenarios where you only want to present textual data, you can simply override ToString() in your data class and return an appropriate text description. In our example, we could rewrite the Character class to return the character’s name from its ToString() override, as follows:

    public override string ToString()
    {
        return _first + " " + _last;
    }

Then at least the text in our ListBox would be a little more representative of the data, as shown here.

But, of course, we want something a little better than just text. Ideally, we’d like to have some formatted text along with an image of the character. This is where a template comes in handy…

What is a Template?

In WPF, a template is just a tree of visual elements (along with some resources and triggers) used to define the look (and often behaviors) of a member of the logical tree. As it builds the element tree, the framework watches for controls and data items that have corresponding templates. When such an element is encountered, the appropriate template is “inflated” into the actual visuals that represent the logical item and those visuals are inserted into the visual tree.

There are different kinds of templates, each of which derives from the FrameworkTemplate base class. The most common template classes are ControlTemplate and DataTemplate. The ControlTemplate class is used to provide the visual representation for a control (like a ListBox). This is the mechanism that enables the WPF lookless control model.

The DataTemplate class is used to provide the visual representation for a data item (like an item within the Items collection of a ListBox). This is the template class we will use to define the visual appearance of our Character items.

Defining a DataTemplate

The first step is to actually define the DataTemplate. In most cases, you will define it as a resource somewhere within your application. For our example, let’s just define it as follows in Window.Resources:

  <Window.Resources>
    <DataTemplate x:Key="CharacterTemplate">
      <Grid>
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="100" />
          <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Image Margin="5" Source="{Binding Image}" />
        <StackPanel Grid.Column="1" Margin="5">
          <TextBlock FontWeight="Bold" Text="{Binding First}" />
        </StackPanel>
      </Grid>
    </DataTemplate>
  </Window.Resources>

Notice that our template tree consists of a root element (a Grid) containing several other visual elements. Some of these visuals, like the Image and the TextBlock, contain properties with bindings set on them. The notation to establish the binding is actually very simple. It merely contains a path to a property of our Character object.

One important thing to notice is that we don’t need to explicitly set a source for bindings within our data template (as long as we are binding to properties of the data item). Since our template represents an actual item of data (a Character), WPF will automatically set that data item as the DataContext of the item container in which the template is inflated. The root element of the template, and consequently, all descendants within the template, will inherit this data context. In this manner, the data context is said to be implicit for elements in the DataTemplate. Namely, the data context is the specific data item that the template represents.

Sidenote: One of the most common questions I see in the WPF Forum is, “How do I get the corresponding data item when someone clicks a button within my data template?” The answer should now be fairly obvious… just look at the DataContext of the original source of the routed event:

    private void OnButtonClick(object sender, RoutedEventArgs e)
    {
        object item = (e.OriginalSource as FrameworkElement).DataContext;
        . . .
    }

Using a DataTemplate with an ItemsControl

Now that we’ve defined a template, we need to somehow instruct our ItemsControl to use it for the data items within its Items collection. There are actually several ways to do this. The simplest approach is to explicitly set the template as the value of the ItemTemplate property of the ItemsControl, as shown here:

  <ListBox Width="200" Height="300"
      ItemTemplate="{StaticResource CharacterTemplate}">
    . . .
  </ListBox>

Now when we run our application, we see that our template is indeed being used to display each data item, as shown here.

Presto! We now have a very simple example that uses a DataTemplate to define the visual representation of items within an ItemsControl. Feel free to download this working sample, if you’d like to play with it and define a more impressive template! 🙂

Using a Type-Specific Data Template

In the example depicted here, we explicitly set the ItemTemplate for our ItemsControl. Using this approach, every item within the Items collection will be displayed using the same template. This is great for collections of similar objects, but what if you have a collection of disparate objects, as shown in the following markup?

<Page
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:sys="clr-namespace:System;assembly=mscorlib">
  <ItemsControl Width="100" Height="100">
    <sys:Int32>30</sys:Int32>
    <sys:DateTime>12/16/1970</sys:DateTime>
    <sys:Boolean>True</sys:Boolean>
    <sys:Boolean>False</sys:Boolean>
    <sys:String>Foo</sys:String>
  </ItemsControl>
</Page>

This results in the following visual representation shown below:

Now suppose you want to use one template to display the Boolean values and a completely different template to display the other value types. To enable this scenario, WPF allows you to specify a type-specific data template.

For example, you might decide that you want each Boolean value to be displayed as a checkbox, rather than the string “True” or “False”. To define such a type-specific data template, simply specify the DataType member on the DataTemplate declaration, as follows:

<Page
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:sys="clr-namespace:System;assembly=mscorlib">
  <Page.Resources>
    <DataTemplate DataType="{x:Type sys:Boolean}">
      <CheckBox IsChecked="{Binding Mode=OneWay}" />
    </DataTemplate>
  </Page.Resources>
  <ItemsControl Width="100" Height="100">
    <sys:Int32>30</sys:Int32>
    <sys:DateTime>12/16/1970</sys:DateTime>
    <sys:Boolean>True</sys:Boolean>
    <sys:Boolean>False</sys:Boolean>
    <sys:String>Foo</sys:String>
  </ItemsControl>
</Page>

Now the ItemsControl is displayed as follows:

Notice that we did not specify an ItemTemplate at all in the above scenario. Instead, when the framework needed to display a Boolean value in the ItemsControl, it performed a resource lookup for a type-specific template matching the Boolean type. Since it found our template containing the CheckBox, it used it. Without the template, it would have fallen back to the earlier observed behavior of calling ToString() on the object to get a textual representation for the Boolean value.

Defining a Default Template for a Given CLR Data Type

In our earlier example, we defined the Character template using a resource key (x:Key=”CharacterTemplate”). We could have defined a default data template by instead using a DataType declaration, as follows:

  <DataTemplate DataType="{x:Type src:Character}">
    <Grid>
      <Grid.ColumnDefinitions>
        <ColumnDefinition Width="100" />
        <ColumnDefinition Width="*" />
      </Grid.ColumnDefinitions>
      <Image Margin="5" Source="{Binding Image}" />
      <StackPanel Grid.Column="1" Margin="5">
        <TextBlock FontWeight="Bold" Text="{Binding First}" />
      </StackPanel>
    </Grid>
  </DataTemplate>

This produces a default visual representation for all Character objects that appear in the logical tree lower than the template declaration. As such, if we do not specify the ItemTemplate property on the ListBox, this template will still be used to display the Character objects. Furthermore, if we include a Character object as the content of a Button (or any other ContentControl), the same template will be used to represent the Character:

  <Button HorizontalAlignment="Center" VerticalAlignment="Center">
    <src:Character First="Maggie" Image="images/maggie.png" />
  </Button>

Sidenote: If you’re curious as to whether you can change the default template for all CLR objects, you cannot. WPF specifically disallows data templates with DataType=”{x:Type sys:Object}”. As such, you are stuck with the ToString() behavior for untemplated CLR objects.

Using a DataTemplateSelector

Assigning a default template based on data type is clearly very powerful. Nonetheless, there may even be times when this does not give you the flexibility you need to select a data template for an item. For example, suppose you want to use one template to represent characters under the age of 21 and a different template to represent those 21 and over.

(Okay, this age-based template selector is probably not a great example for cartoon characters… perhaps a different data template for girls and boys would be better… but honestly, that’s too easy to achieve using a single data template with a data trigger… so humor me and let’s just go with the age thing… ;))

For even more flexibility in selecting an item template, you can implement a custom data template selector. A template selector is a class that derives from DataTemplateSelector and overrides the SelectTemplate method to return a template based on custom code execution. Here is a very simple example to meet the needs described above:

public class CharacterTemplateSelector : DataTemplateSelector
{
    private DataTemplate _childTemplate = null;
    public DataTemplate ChildTemplate
    {
        get { return _childTemplate; }
        set { _childTemplate = value; }
    }

    private DataTemplate _adultTemplate = null;
    public DataTemplate AdultTemplate
    {
        get { return _adultTemplate; }
        set { _adultTemplate = value; }
    }

    public override DataTemplate SelectTemplate(object item,
        DependencyObject container)
    {
        if (item is Character)
        {
            return (item as Character).Age >= 21
                ? _adultTemplate : _childTemplate;
        }
        return base.SelectTemplate(item, container);
    }
}

Now to use the template selector, we simply declare an instance as a resource and set the ChildTemplate and AdultTemplate properties appropriately:

  <src:CharacterTemplateSelector x:Key="CharacterTemplateSelector"
      ChildTemplate="{StaticResource CharacterTemplate}"
      AdultTemplate="{StaticResource AdultCharacterTemplate}" />

Then we set the ItemTemplateSelector property on the ItemsControl using a resource reference, as follows:

  <ListBox Width="200" Height="300"
      ItemTemplateSelector="{StaticResource CharacterTemplateSelector}">
    . . .
  </ListBox>

This custom data template selector is also included in the downloadable sample for this article.

What’s next?

This ends our discussion on data templates and the WPF content model for the ItemsControl classes. In the next episode, ‘G’ is for Generator, we will look at item containers and item container generators. (And yes, I realize we’re skipping a couple of letters, but you don’t really want 26 posts on ItemsControl, do you?)