Hi,
- The current version Beta 12.2 supports the following RelativeSource modes: Seft and TemplatedParent. The mode "AncestorType" is not yet supported (it is on the roadmap for the coming months).
- The design-time error "
Type 'RelativeSource' is used like a markup extension but does not derive from MarkupExtension" was a bug and it will be fixed in the upcoming Beta 12.3.
- At design-time, the XAML preview sometimes did not show the bindings, even though they did work at runtime. This will be fixed in the upcoming Beta 12.3.
Here is the explanation of each supported RelativeSource mode:
- Self
Use "Self" if you want to bind one property of an element to another property on the same element. With this mode, the element on which the binding is applied will be the source of the binding.
Here is an example:
Code: Select all
<TextBlock Text="{Binding Width, RelativeSource={RelativeSource Mode=Self}}" x:Name="TextBlock1" Width="200"/>
In this example, the TextBlock will display the text "200", because the Text property is bound to the Width property.
Please note that this is NOT the same as:
Code: Select all
<TextBlock Text="{Binding Width}" x:Name="TextBlock1" Width="200"/>
The line above will NOT work because it will be looking for a property "Width" on the DataContext. By "DataContext" we mean the content of the property "TextBlock1.DataContext". The DataContext is an inherited property, which means that "TextBlock1.DataContext" will have the same value as the DataContext property of the parent of the TextBlock.
An alternative way to achieve the same result as "Selft" is to use "ElementName". With "ElementName" you can tell it to use the element itself as the source of the binding. Here is an example:
Code: Select all
<TextBlock Text="{Binding Width, ElementName=TextBlock1}" x:Name="TextBlock1" Width="200"/>
- TemplatedParent
Use "TemplatedParent" if you are inside a ControlTemplate and you want to bind a property of an element to a property of the templated control.
For example, consider the following XAML code:
Code: Select all
<Border>
<Border.Resources>
<Style x:Key="MyRoundButtonStyle" TargetType="Button">
<!-- Set the default value for some properties of the button: -->
<Setter Property="Background" Value="Gray"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Padding" Value="12"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<!-- Define how the button will be rendered: -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse
Fill="{Binding Background, RelativeSource={RelativeSource Mode=TemplatedParent}}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"/>
<ContentPresenter
Content="{Binding Content, RelativeSource={RelativeSource Mode=TemplatedParent}}"
HorizontalAlignment="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource Mode=TemplatedParent}}"
VerticalAlignment="{Binding VerticalContentAlignment, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Border.Resources>
<Button x:Name="MyTemplatedButton"
Content="OK"
Style="{StaticResource MyRoundButtonStyle}"
Width="50"
Height="50"
Background="Blue"
Foreground="White"/>
</Border>
In the code above, we create a round button by creating a new style using a ControlTemplate. The "Fill" property of the ellipse has a binding to the "Background" property of the templated button.
Please note that the two following lines are strictly equivalent:
Code: Select all
<Ellipse Fill="{Binding Background, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
and
Code: Select all
<Ellipse Fill="{TemplateBinding Background}"/>
The main advantage of the "Binding" syntax compared to the "TemplateBinding" syntax is that the former allows you to specify a "Converter" to convert the bound value via a class that inherits from IValueConverter.
Regards,
JS-Support