TemplateBinding inside ControlTemplate.Triggers

One of the limitations of TemplateBinding Markup in WPF is the fact that we cannot use it inside the ControlTemplate.Triggers because it really doesn’t work, since as Mike Hillberg said here, “TemplateBinding is a lightweight, but less functional, version of a Binding with a RelativeSource of TemplatedParent.  One of the things that a TemplateBinding can’t do is work within the ControlTemplate.Triggers; TemplateBinding only works within the template content” .

So we have this:

       MyControl.cs

  1: 	public class MyControl : Control
  2: 	{
  3: 
  4: 		public Boolean Selected
  5: 		{
  6: 			get { return (Boolean)GetValue(SelectedProperty); }
  7: 			set { SetValue(SelectedProperty, value); }
  8: 		}
  9: 
 10: 		// Using a DependencyProperty as the backing store for Selected.  This enables animation, styling, binding, etc...
 11: 		public static readonly DependencyProperty SelectedProperty =
 12: 			DependencyProperty.Register("Selected", typeof(Boolean), typeof(MyControl), new UIPropertyMetadata(false));
 13: 
 14: 
 15: 
 16: 		public Brush SelectedColor
 17: 		{
 18: 			get { return (Brush)GetValue(SelectedColorProperty); }
 19: 			set { SetValue(SelectedColorProperty, value); }
 20: 		}
 21: 
 22: 		// Using a DependencyProperty as the backing store for SelectedColor.  This enables animation, styling, binding, etc...
 23: 		public static readonly DependencyProperty SelectedColorProperty =
 24: 			DependencyProperty.Register("SelectedColor", typeof(Brush), typeof(MyControl), new UIPropertyMetadata(Brushes.Red));
 25: 
 26: 
 27: 		public MyControl()
 28: 		{			
 29: 		}
 30: 
 31: 		protected override void OnInitialized(EventArgs e)
 32: 		{
 33: 			base.OnInitialized(e);
 34: 
 35: 			this.MouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(MyControl_MouseLeftButtonDown);
 36: 		}
 37: 
 38: 		void MyControl_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
 39: 		{
 40: 			MessageBox.Show(this.SelectedColor.ToString());
 41: 			this.Selected = !this.Selected;
 42: 		}
 43: 	}
 44: 

      Window1.xaml

  1: <Window x:Class="WpfApplication13.Window1"
  2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4: 	xmlns:local="clr-namespace:WpfApplication13"
  5:     Title="Window1" Height="300" Width="300">
  6:     <Grid>
  7: 		<local:MyControl x:Name="ctrl1">
  8: 			<local:MyControl.Template>
  9: 				<ControlTemplate TargetType="{x:Type local:MyControl}">
 10: 					<Grid Background="Green" x:Name="source"/>
 11: 					<ControlTemplate.Triggers>
 12: 						<Trigger Property="Selected" Value="true">
 13: 							<Setter TargetName="source" Property="Background" Value="{TemplateBinding SelectedColor}"/>
 14: 						</Trigger>
 15: 						<Trigger Property="Selected" Value="false">
 16: 							<Setter TargetName="source" Property="Background" Value="Green"/>
 17: 						</Trigger>
 18: 					</ControlTemplate.Triggers>
 19: 				</ControlTemplate>
 20: 			</local:MyControl.Template>
 21: 		</local:MyControl>
 22: 	</Grid>
 23: </Window>
 24: 

When we compile we get the following error, "Cannot convert the value in attribute ‘Value’ to object of type ”.  Error at object ‘System.Windows.Setter’ in markup file ‘WpfApplication13;component/window1.xaml’ Line 13 Position 58."

So how can we solve this problem?

   Since the problem here is that TemplateBinding is not supported inside the ControlTemplate.Triggers, we have to find another way to make the binding, and so we just change the line 13 to

  1: 							<Setter TargetName="source" Property="Background" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedColor}"/>

      And if we look at the TemplateBinding Markup page in MSDN, the usage of TemplateBinding is similar to the Binding Markup using TemplatedPart as the RelativeSource, like {Binding RelativeSource={RelativeSource TemplatedParent}, Path=DependencyPropertyToBind}

Hope this helps.

3 thoughts on “TemplateBinding inside ControlTemplate.Triggers”

Leave a Reply

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