Controlling The DataTemplate

SelectedItemImageWindows 8 has now shipped and developers are busy building Windows Store Applications (bad name).  Developers who have experience working with Xaml have expectations on how Xaml should behave. The other day I was trying to do something I have done before.  I wanted to change the DataTemplate of an item in an items control based upon an item being selected in an item control.

In Xaml, Items Controls are made up of different template. These templates are used to control the look and behavior of the items in the list.  The power of Xaml is data binding.  Take a collection of objects and bind it to an Items Control.  Each item is displayed and by default, the string representation is displayed.  To change this behavior you have to setup a DataTemplate.  This template is then applied to each item in the collection. The problem with DataTemplates are that they don’t respond to the interactions of the control.

The interactions are achieved through visual states.  To modify these interactions you have to edit the ItemsContainerStyle.  There are the visual states are laid out through VisualStateGroups.  Here is where the Selected style is defined.  The problem is the data in the DataTemplate has no knowledge of this template or it’s interactions.  In fact DataTemplates aren’t associated with any specific control.  The same DataTemplate can be used by any control. 

To solve my problem I had to wire the DataTemplate to the states in the ItemsContainerStyle. This is an instance of a specific control.  For a GridView it is a GridViewItem. For a ListView it is a ListViewItem.  You get the point.  In prior Xaml techologies you would use AncestorBinding to walk up the object tree until you found the Item control.  You would then bind the IsSelected property to a trigger.  This allowed you to apply different styles based on this property. 

In Windows 8 Xaml, you don’t have ancestry binding nor do you have triggers.  So how do you achieve the same thing in your Windows Store application? There are RelativeSource bindings available but ancestry mode is not there.  The only mode that can help is the TemplateParent mode.  So I started out hoping that the TemplateParent was the Item control but this was not the case. For DataTemplates the parent is usually a ContentPresenter, one of the parts within the ItemsContainerStyle.

Now I can pass the IsSelected property through to the DataTemplate. First I template bind the IsSelected property to the Tag property of the ContentPresenter.

ContentPresenter

I then set up two grids in the DataTemplate to control the content that is visible based on the  IsSelected property.  I created two controls one for normal view and one for a selected view. Trough value converters I convert the value from the Tag into a visibility for the grid.

DataTemplate

That is it. This all that is needed.  Now my selected item view will be displayed when the item is selected.  For the most part the Xaml developers will feel comfortable developing Windows 8 Store apps. There will be time where you have to find alternatives to what you’re used to but those should be the exception and not the rule. 

As I come across these I differences I will continue to post them here.  You can download some sample code here.

This entry was posted in Metro, User Experience, Windows 8, WinRT. Bookmark the permalink.

5 Responses to Controlling The DataTemplate

  1. Pingback: Windows 8 - Controlling The DataTemplate

  2. Pingback: Windows Store Developer Links – 2012-11-13 | Dan Rigby

  3. Hey Dave, thanks for the article. I am trying to get one level higher, and bind to a property on the GridView itself, so that I can change the state of all the items in my GridViewItemList all at once (e.g. change the visibility of an element in my DataTemplate for every item in the list by binding to a single element on the GridView). Is this possible?
    Thanks,
    Bob

    • dmd0822 says:

      You might be able to do it by giving the GridView a x:name and then do an element binding. Then you binding may look something like this: {Binding propertyName, Element=elementName}.

      Hope that helps.

  4. Robert says:

    Hi Dave! Exactly what I was looking for! Thanks!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s