EditCategory
Data Binding
EditQuestion
What is the difference between Source, RelativeSource, and ElementName when creating a Binding?
EditAnswer
The first major difference is that these three properties are mutually exclusive: only one of them can be set on a
Binding.
Source property:The
Source property is used to specify an object reference on which the binding
Path or
XPath will be evaluated. The
Source property is usually used when the object on which the Binding is set is known and differs from the
DataContext.
Source property examples:XAML:
<CustomClass1 Property1="{Binding Source={x:Static DateTime.Now}, Path=Day}"/>Code:
Binding my_binding = new Binding();
my_binding.Source = my_data_object;
RelativeSource property:The
RelativeSource property is used to specify as a source an object that is positioned relatively to the current object. Once again, this property is used when there is a need to specify a source other than the
DataContext of the object.
There are three normal ways of using of the
RelativeSource property.
The first usage is to access
Self. Specifying a
Self relative source allows referencing itself as the source. This is particularly useful when we want to bind a property of an object on another property of the same object.
RelativeSource Self examples:XAML:
<TextBlock Width="{Binding RelativeSource={RelativeSource Self}, Path=Parent.ActualWidth}"/>Code:
binding my_binding = new Binding();
my_binding.RelativeSource = RelativeSource.Self;
The second usage of
RelativeSource is
FindAncestor mode. FindAncestor mode allows the retrieval of an ancestor of the current object based on its type and/or an ancestor level. While the Type is mandatory, the level is not. If level is not specified or if the provided value does not have a match, then the first element with matching
Type is used (i.e., if 1 is specified, the first occurrence of
Type is used; if 3 is used, the third occurrence of
Type will be used).
RelativeSource FindAncestor examples:XAML:
<StackPanel Background="Blue">
<TextBlock Background="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type StackPanel}, AncestorLevel=1},Path=Background}" />
</StackPanel>
Code:
Binding new_binding = new Binding();
new_binding.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(StackPanel), 1);
The third usage is
TemplatedParent mode.
TemplatedParent mode allows the retrieval of the object being templated (if within a template). If you are within a
ControlTemplate, templating a
Button, then the result of the
TemplatedParent RelativeSource will be the
Button object instance.
RelativeSource TemplatedParent examples:XAML:
<Window>
<Window.Resources>
<ControlTemplate x:Key="myButtonTemplate" TargetType="{x:Type Button}">
<StackPanel Background="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background}"/>
</ControlTemplate>
</Window.Resources>
<Button Template="{StaticResource myButtonTemplate}" Background="Blue"/>
</Window>
Code:
Binding new_binding = new Binding();
new_binding.RelativeSource = RelativeSource.TemplatedParent;
ElementName property:The
ElementName property is used to reference an object by the name of the object. This is particularly useful in XAML, where you can directly reference other elements defined in XAML.
XAML:
<StackPanel Background="Blue">
<Button x:Name="refButton" Background="Orange"/>
<Button Background="{Binding ElementName=refButton, Path=Background}"/>
</StackPanel>
Code:
Binding new_binding = new Binding();
new_binding.ElementName = "refButton";