Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Trying to get the bindings right for a certain ControlTemplate I wanted to have for a TabControl lead me to an interesting observation on TemplateBinding that was not so obvious. In the TabControl's ControlTemplate, I wanted to have an inner ItemsControl binding to the templated TabControl's Items (and thus replace the default TabPanels).
It ended up working with a RelativeSource binding like this:
<ControlTemplate x:Key="CustomTabControlTemplate" TargetType="{x:Type TabControl}">
...
<ItemsControl Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" >
<ItemsControl.ItemsSource>
<Binding Mode="OneWay" Path="Items">
<Binding.RelativeSource>
<RelativeSource
Mode="TemplatedParent"
/>
</Binding.RelativeSource>
</Binding>
</ItemsControl.ItemsSource>
</ItemsControl>
I was intrigued that using the more usual TemplateBinding did not work (you get a compile time error):
<ItemsControl ItemsSource="{TemplateBinding Items}" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" />
From the TemplateBinding docs, one can get the (wrong) impression that it should actually work. It says:
A TemplateBinding is an optimized form of a Binding for template scenarios, analogous to a Binding constructed with {Binding RelativeSource={RelativeSource TemplatedParent} Mode=OneWay}.
The word "analogous" is misleading. At a search, it was clear that there are significant differences under the hood between Binding and TemplateBinding. Some of them are described here, however, none of them seemed to apply, which is why I tried to look again more carefully at the docs. And there's the explanation right on the TemplateBinding docs page: unlike a Binding, a TemplateBinding can only bind a DependencyProperty to another DependencyPropery (IMHO, the wording of "targetProperty" in the docs below is confusing/wrong from a WPF binding terminology perspective, because the property on the type being templated is actually the source, the target being propertyName !):
|
|
|
|
But Items in an ItemsControl is not a DependencyProperty (ItemsSource is !) which is why only a RelativeSource Binding works in this case.