DataTemplate and Bindings

In Windows 8 there are a few controls that rely on a DataTemplate to show item collections.

The DataTemplate is used to define visual layout for each item that will be rendered in an ItemsControl, it data binds nicely to collections of objects. It then iterates through the collection and uses each item as context for every new Template that is created.

Binding to Commands in the DataTemplate

When binding Commands to controls we usually bind them to Commands in the ViewModel, set as datacontext.

But if you, for example, have a button defined in the DataTemplate and bind that to a Command defined in your ViewModel, set as the datacontext for the page, it won’t work.

Why doesn’t Binding to Commands work in the DataTemplate?

The reason that the Command isn’t executed is that the Command can’t be found.

Since it’s an item in the collection that’s actually the current DataContext for the item being created, the command can’t be found if it’s defined globally in your ViewModel.

The solution is to refer the Command binding to look further up the object tree to find the Command.

In WPF it was solved using FindAncestor, but that’s removed now in WinRT.

The easiest way to solve it is to actually give the view/page an x:Name. Then refer to the Command in the binding as DataContext.MyCommandName, and set ElementName to the name of the view/page. See code snippets below, how the Command is defined, the x:Name set in Page and the Command defined in the ViewModel.

Code Snippets

ViewModel snippet:

        private RelayCommand headerClickedCommand;
        public RelayCommand HeaderClickedCommand
        {
            get { return headerClickedCommand ?? (headerClickedCommand = new RelayCommand(ExecuteHeaderClickedCommand)); }
        }

        private void ExecuteHeaderClickedCommand()
        {
            NavigateSomewhere();
        }

XAML PageRoot snippet:

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      x:Name="MyView"
      ...
      >

XAML DataTemplate snippet:

<DataTemplate>
  <Grid Margin="0,0,0,2">
    <Button Foreground="{ThemeResource ApplicationHeaderForegroundThemeBrush}"
				    AutomationProperties.Name="Group Title"
                                    Command="{Binding DataContext.HeaderClickedCommand, ElementName=MyView}"
                                    Style="{StaticResource TextBlockButtonStyle}">
     <StackPanel Orientation="Horizontal">
       <TextBlock Text="{Binding Category}" Margin="0,-11,10,10" Style="{StaticResource SubheaderTextBlockStyle}" TextWrapping="NoWrap" />
        <TextBlock Text="{StaticResource ChevronGlyph}" FontFamily="Segoe UI Symbol" Margin="0,-11,0,10" Style="{StaticResource SubheaderTextBlockStyle}" TextWrapping="NoWrap" />
      </StackPanel>
    </Button>
  </Grid>
</DataTemplate>

Happy Coding 🙂

Windows 8.1 Command Binding in a DataTemplate
Tagged on:     

9 thoughts on “Windows 8.1 Command Binding in a DataTemplate

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.