Using ViewModels and DataTemplates to compose your UI


Several drops ago we introduced a ViewModel composition spike. The purpose of this spike was to introduce a different way to compose your UI that WPF offers. That is instead of having your views and regions be UI-Elements, having them as pure models. What I mean by this is instead of having a Employee Region which is a tab, that contains EmployeeViews, you have a model (the region) that contains Employees. Likewise instead of of having a panel that displays a CustomerView, you have a  model that contains a single Customer. So how do I get my Employee region to display as a Tab, and my Employee to display itself in the same way as the EmployeeView? The answer is using DataTemplates. Using DataTemplates, you can define the UI rendering for a specific type (in this case the Employee and the EmployeeRegion). The nice thing for the no code-behind zealots among us is that there is absolutely NO CODE BEHIND in a DataTemplate.

Below you can see an example of what an Employee template might look like:

<DataTemplate DataType="{x:Type Employee}">
    <Grid x:Name="GeneralGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition Width="5"></ColumnDefinition>
            <ColumnDefinition Width="*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <TextBlock Text="First Name:" Grid.Column="0" Grid.Row="0"></TextBlock>
        <TextBlock Text="Last Name:" Grid.Column="2" Grid.Row="0"></TextBlock>
        <TextBlock Text="Phone:" Grid.Column="0" Grid.Row="2"></TextBlock>
        <TextBlock Text="Email:" Grid.Column="2" Grid.Row="2"></TextBlock>
 
        <TextBox x:Name="FirstNameTextBox" Text="{Binding Path=FirstName}"
            Grid.Column="0" Grid.Row="1"></TextBox>
        <TextBox x:Name="LastNameTextBox" Text="{Binding Path=LastName}" 
            Grid.Column="2" Grid.Row="1"></TextBox>
        <TextBox x:Name="PhoneTextBox" Text="{Binding Path=Phone}" 
            Grid.Column="0" Grid.Row="3"></TextBox>
        <TextBox x:Name="EmailTextBox" Text="{Binding Path=Email}" Grid.Column="2" 
            Grid.Row="3"></TextBox>
    </Grid>
</DataTemplate>

Julian has a set of posts where he is discussing this interesting approach to composition. He’s done two posts so far, but I am sure there’s much more to come.

Using the Presentation Model in WPF

First approach to Presentation Model with DataTemplates

Great stuff!


Comments (9)

  1. Jens Winter says:

    Hi Glenn,

    First thanks to you and the prism team for the great work.

    I must say that I really like the approach you are taking with the view composition spike. The working feels very natural to me and our team.

    Can’t wait for the next drop!

    Cheers,

    Jens

  2. Glenn Block says:

    Thanks Jens, we’re glad you are finding it useful.

  3. A new drop of Prism has been published last Thursday. Among other things, in this drop we refactored

  4. Winston says:

    Hi Glenn

    Any ideas about how to get events to work with control templates and data templates? I’ve seen plenty of samples that use Commands but nothing on how to wire up events. Note that you get a compile error if you add an event handler in a control/data template.

    Cheers

    Winston

  5. @Winston

    You can’t use events in a DataTemplate, but you can use Commands. The Composite Application Library includes a DelegateCommand that allows you to pass in delegates for the Execute and CanExecute. If you bind UIElements to this  command, you can wire up to your custom code in either your code behind, or in a presenter. In that custom code, you can then throw an event, or use the event aggregator.

    Another approach is to create custom ICommands specific to the different actions that are being performed. The advantage of DelegateCommand is that you don’t have to create all the custom command instances.

    Let me know if this makes sense.

    Glenn

    Does this make sense?>

  6. Hi Glenn, thanks for linking to my blog 🙂

    We changed the blog engine, so the new links flor the posts Glenn was talking about are:

    http://blogs.southworks.net/jdominguez/2008/04/using-the-presentation-model-in-wpf/

    and

    http://blogs.southworks.net/jdominguez/2008/04/using-the-presentation-model-in-wpf/

    Thanks