Silverlight 3 introduced the RelativeSource Binding that we know from WPF.
As the name indicates, RelativeSource is used when setting up a relative Data Binding.
Lets look at an example. If we want to bind the ToolTip to Content property on the same element, we can say:
<Button Content="Button" Height="25" Width="75"
ToolTipService.ToolTip="{Binding Content,
RelativeSource={RelativeSource Self}}" />
As you can see, when binding to ourself, we don’t need any name on the element.
Another option is to use TemplatedParent.
Lets say that we want to change a Slider template to include a TextBox. And that TextBox should always display the same value as the slider.
Here is the full code:
<Slider Height="84" Margin="229,151,200,0" VerticalAlignment="Top">
<Slider.Template>
<ControlTemplate>
<Grid x:Name="Root">
<Grid.Resources>
<ControlTemplate x:Key="RepeatButtonTemplate">
<Grid x:Name="Root" Opacity="0"
Background="Transparent"/>
</ControlTemplate>
</Grid.Resources>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackPanel>
<Grid x:Name="HorizontalTemplate"
Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Rectangle x:Name="TrackRectangle"
Fill="#FFE6EFF7" Stroke="#FFA3AEB9"
StrokeThickness="{TemplateBinding BorderThickness}"
RadiusX="1" RadiusY="1" Height="3" Margin="5,0,5,0"
Grid.Column="0" Grid.ColumnSpan="3"/>
<Rectangle x:Name="HorizontalTrackRectangleDisabledOverlay"
Fill="White" RadiusX="1" RadiusY="1" Height="3"
Margin="5,0,5,0" Opacity=".55" Visibility="Collapsed"
Grid.Column="0" Grid.ColumnSpan="3"/>
<RepeatButton x:Name="HorizontalTrackLargeChangeDecreaseRepeatButton"
Height="18" IsTabStop="False" Template="{StaticResource
RepeatButtonTemplate}" Grid.Column="0"/>
<Thumb x:Name="HorizontalThumb" Height="18" Width="11" IsTabStop="True"
Grid.Column="1"/>
<Rectangle x:Name="ThumbDisabledOverlay" Fill="White" RadiusX="2"
RadiusY="2" Width="11" Opacity=".55" Visibility="Collapsed"
Grid.Column="1"/>
<RepeatButton x:Name="HorizontalTrackLargeChangeIncreaseRepeatButton"
Height="18" IsTabStop="False"
Template="{StaticResource RepeatButtonTemplate}"
Grid.Column="2"/>
</Grid>
<TextBox Width="200" Text="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=Value}"/>
</StackPanel>
</Grid>
</ControlTemplate>
</Slider.Template>
</Slider>
The line that we are interested in is this:
<TextBox Width="200"
Text="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=Value}"/>
The TextBox is inside the Slider Template. We use TemplatedParent to bind the Text Property of the TextBox to it’s parent’s Value property (the slider is the parent).
There is a important difference between using a Binding with RelativeSource like this, and using the normal TemplateBinding.
The TemplateBinding is a one-way binding. From the templated parent to a element inside the template. If you need binding both ways, then you should use a Binding with RelativeSource as above.
WPF has two other options that Silverlight don’t: PreviousData and FindAncestor.
With PreviousData we can bind the previous data item in the list of data items being displayed. And FindAncestor refers to the ancestor in the parent chain of the data-bound element