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 🙂
Thank you so much for this!!! I’m almost in the verge of giving up in searching for this solution. I’ve searched countless days and forums for command binding in Windows phone 8.1 but got no solution. And to think this is years older than I thought. I almost change the layout of my application and that’s frustrating because I love the layout that I made. Thanks again and hope you can still read my comment. 😀
Thanks and glad it helped some one. It’s comments like these that make me wish I had more time to spend on blogging.
Happy coding man! 🙂
This helped! thanks a lot!!
Glad to hear that, yw 🙂
Your code is working fine and many many thanks for this post, It has saved a lot of time and many many thanks. But how do I pass the Button’s Content as a command parameter or any other way, If you guide then that would be a great help.
Pingback: WinRT 开发:在 MVVM 模式中,关于绑定的几处技巧 | 一世浮华一场空
Pingback: WinRT 开发:在 MVVM 模式中,关于绑定的几处技巧 - .net开发技术分享
Pingback: WinRT 开发:在 MVVM 模式中,关于绑定的几处技巧 - 编程技术分享
Great 😉 needed, thanks