CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Glenn Block

Another ALT.NET guy at Microsoft

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!


Published May 24 2008, 09:10 AM by Glenn Block
Filed under: ,

Comments

Rob said:

Now you're starting to think like a WPF developer!!!  You'll find that this is what truly unlocks all of WPF's possibilities.

# May 24, 2008 3:18 PM

Bob on Medical Device Software » Blog Archive » Drop, Spike… Huh? said:

Pingback from  Bob on Medical Device Software  &raquo; Blog Archive   &raquo; Drop, Spike&#8230; Huh?

# May 24, 2008 7:46 PM

Dew Drop - May 25, 2008 | Alvin Ashcraft's Morning Dew said:

Pingback from  Dew Drop - May 25, 2008 | Alvin Ashcraft's Morning Dew

# May 25, 2008 11:38 AM

Josh Smith said:

This sounds about right to me.  This is the "right" way to do data visualization in WPF, so I'm glad to see you guys are starting to do it as well.

Check this out for another perspective: www.codeproject.com/.../TreeViewWithViewModel.aspx

Josh

# June 10, 2008 6:27 PM

Brett Ryan said:

I'm on the hunt for a way to have capture events from this approach, specifically where an ItemsControl is used, like a ListBox, how do you capture a double click event, or better still, wire a Command="{Binding ItemActivated"} action to be captured. I don't care if it's a global command I just want something, but at the moment I can't figure anything out :(

-Brett

# June 12, 2008 5:44 AM

Glenn Block said:

@Brett

Check out the DelegateCommand. Using the command you can pass in delegates for the CanExecute and Execute.

# June 17, 2008 11:12 PM

Glenn Block said:

@Josh

Great article. Thanks for the link.

# June 17, 2008 11:13 PM

Mike said:

Great Post!  Thanks for the samples...

I do have one question however, if I need to have a combobox in my datatemplate, how would I go about setting it's (the combobox's) datacontext?  I have created a couple of ObjectDataSources and added them to a separate ResourceDictionary and then in the datatemplate I simply bind the datacontext to one of those DataProviders.  I'm sure there are other/better ways to do it, any suggestions?  I guess all I'm really trying to do is populate that combobox with a list of states... (i.e. - CA, MN, NY, WI, Etc.)

# August 21, 2008 2:27 AM

Glenn Block said:

Hi @Mike

What you can do is hang your combo list off of your presentation model as a property, say a List<String>, or a List<City> Then just bind to it.

Because its a ViewModel, you can decorate it with whatever it needs tot drive the UI.

# August 21, 2008 2:37 AM

Mike said:

Thanks for the reply...I'm VERY new to this whole MVx architecture and it's got my head spinning...it seems the more I read, the more I become confused because everyone has a different opinion on how to implement a pattern...anyway...

In the example above I could/would create a property called City on the EmployeeModel and then that property would be populated with a generic list that is created by a call to a datastore (via DAL) that would retrieve the list of cities?

Thanks so much for responding...

# August 21, 2008 1:39 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add

About Glenn Block

Glenn is a PM for the new Managed Extensibility Framework in .NET 4.0. Prior to Microsoft, he worked for 10 years in various startups and ISVs wearing many different hats all related to developing software. Glenn has been writing code practically since the time he learned how to ride a bicycle. When he's not writing code, he's continuously improving on ways to build better software. Glenn is a geek at heart and spends a good portion of the rest of this time spreading that geekdom through conferences, and the community through groups such as ALT.NET. When he's not working and playing with technology, he spends his time with his wife and four year old daughter either at their Seattle apartment or at one of the local coffee shops. Check out Devlicio.us!

Our Sponsors

Free Tech Publications

This Blog

Syndication

News

View Glenn Block's profile on LinkedIn

Me