How do I use RelativeSource with WPF bindings and what are the different use-cases?
How do I use RelativeSource with WPF bindings and what are the different use-cases?
If you want to bind to another property on the object:
{Binding Path=PathToProperty, RelativeSource={RelativeSource Self}}
If you want to get a property on an ancestor:
{Binding Path=PathToProperty,
RelativeSource={RelativeSource AncestorType={x:Type typeOfAncestor}}}
If you want to get a property on the templated parent (so you can do 2 way bindings in a ControlTemplate)
{Binding Path=PathToProperty, RelativeSource={RelativeSource TemplatedParent}}
or, shorter (this only works for OneWay bindings):
{TemplateBinding Path=PathToProperty}
Binding RelativeSource={
RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemType}
}
...
The default attribute of RelativeSource is the Mode property. A complete set of valid values is given here (from MSDN):
PreviousData Allows you to bind the previous data item (not that control that contains the data item) in the list of data items being displayed.
TemplatedParent Refers to the element to which the template (in which the data-bound element exists) is applied. This is similar to setting a TemplateBindingExtension and is only applicable if the Binding is within a template.
Self Refers to the element on which you are setting the binding and allows you to bind one property of that element to another property on the same element.
FindAncestor Refers to the ancestor in the parent chain of the data-bound element. You can use this to bind to an ancestor of a specific type or its subclasses. This is the mode you use if you want to specify AncestorType and/or AncestorLevel.
Don't forget TemplatedParent:
<Binding RelativeSource="{RelativeSource TemplatedParent}"/>
or
{Binding RelativeSource={RelativeSource TemplatedParent}}
I am constantly updating my research on Binding.
Original Here
DataContext is the DependencyProperty included in the FrameworkElement.
PresentationFramework.dll
namespace System.Windows
{
public class FrameworkElement : UIElement
{
public static readonly DependencyProperty DataContextProperty;
public object DataContext { get; set; }
}
}
And, all UI Controls in WPF inherit the FrameworkElement class.
At this point in learning Binding or DataContext, you don't have to study FrameworkElement in greater depth.
However, this is to briefly mention the fact that the closest object that can encompass all UI Controls is the FrameworkElement.
Binding can directly recall values for the DataContext type format starting with the nearest DataContext.
<TextBlock Text="{Binding}" DataContext="James"/>
The value bound to Text="{Binding}" is passed directly from the nearest DataContext, TextBlock.
Therefore, the Binding result value of Text is 'James'.
Type integer
When assigning a value to DataContext directly from Xaml, resource definitions are required first for value types such as Integer and Boolean.
Because all strings are recognized as String.
mscrolib in Xaml
Simple type variable type is not supported by standard.
You can define it with any word, but mostly usesyswords.
xmlns:sys="clr-namespace:System;assembly=mscorlib"
2. Create YEAR resource key in xaml
Declare the value of the type you want to create in the form of a StaticResource.
<Window.Resources>
<sys:Int32 x:Key="YEAR">2020</sys:Int32>
</Window.Resources>
...
<TextBlock Text="{Binding}" DataContext="{StaticResource YEAR"/>
All type of value
There are very few cases where Value Type is binding directly into DataContext.
Because we're going to bind an object.
<Window.Resources>
<sys:Boolean x:Key="IsEnabled">true</sys:Boolean>
<sys:double x:Key="Price">7.77</sys:double>
</Window.Resources>
...
<StackPanel>
<TextBlock Text="{Binding}" DataContext="{StaticResource IsEnabled}"/>
<TextBlock Text="{Binding}" DataContext="{StaticResource Price}"/>
</StackPanel>
Another type
Not only String but also various types are possible. Because DataContext is an object type.
In using Binding at WPF, most developers are not fully aware of the existence, function and importance of DataContext.
It may mean that Binding is being connected by luck.
Especially if you are responsible for or participating in a large WPF project, you should understand the DataContext hierarchy of the application more clearly. In addition, the introduction of WPF's various popular MVVM Framework systems without this DataContext concept will create even greater limitations in implementing functions freely.
string property
<TextBox Text="{Binding Keywords}"/>
<CheckBox x:Name="usingEmail"/>
<TextBlock Text="{Binding ElementName=usingEmail, Path=IsChecked}"/>
<TextBlock Margin="5,2" Text="This disappears as the control gets focus...">
<TextBlock.Visibility>
<MultiBinding Converter="{StaticResource TextInputToVisibilityConverter}">
<Binding ElementName="txtUserEntry2" Path="Text.IsEmpty" />
<Binding ElementName="txtUserEntry2" Path="IsFocused" />
</MultiBinding>
</TextBlock.Visibility>
</TextBlock>
<TextBlock x:Name="txt" Text="{Binding ElementName=txt, Path=Tag}"/>
If you have to bind your own property, you can use Self Property Binding, instead of using Element Binding.
You no longer have to declare x:Name to bind your own property.
<TextBlock Text="{Binding RelativeSource={RelativeSource Self}, Path=Tag}"/>
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=Title}"/>
In addition to the properties of the controls found, the properties within the DataContext object can be used if it exists.
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.Email}"/>
This is a method that can be used within ControlTemplate, and you can import the control that is the owner of the ControlTemplate.
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<TextBlock Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
You can access to all Property and DataContext.
<TextBlock Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}"/>
You can access binding property value directly.
1. Declarestatic property.
namespace Exam
{
public class ExamClass
{
public static string ExamText { get; set; }
}
}
2. Using static class in XAML.
<Window ... xmlns:exam="clr-namespace:Exam">
3. Binding property.
<TextBlock Text="{Binding exam:ExamClass.ExamText}"/>
Or, you can set Resource key like using Converter.
<Window.Resource>
<cvt:VisibilityToBooleanConverter x:Key="VisibilityToBooleanConverter"/>
<exam:ExamClass x:Key="ExamClass">
</Window.Resource>
...
<TextBlock Text="{Binding Source={StaticResource ExamClass}, Path=ExamText}"/>
I have never used the Static Property under normal circumstances. This is because data that deviates from its own DataContext can disrupt the flow of whole WPF applications and impair readability significantly. However, this method is actively used in the development stage to implement fast testing and functions, as well as in the DataContext (or ViewModel).
Using ElementBinding through connected control is not a functional problem,
but it breaks the fundamental pattern of Binding.
<TextBox x:Name="text" Text="{Binding UserName}"/>
...
<TextBlock Text="{Binding ElementName=text, Path=Text}"/>
Good Binding
<TextBox Text="{Binding UserName}"/>
...
<TextBlock Text="{Binding UserName}"/>
<Window x:Name="win">
<TextBlock Text="{Binding ElementName=win, Path=DataContext.UserName}"/>
...
Good Binding
<Window>
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.UserName}"/>
...
Great!
<Window>
<TextBlock DataContext="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext}"
Text="{Binding UserName}"/>
...
<TextBlock x:Name="txt" Text="{Binding ElementName=txt, Path=Foreground}"/>
Good Binding
<TextBlock Text="{Binding RelativeSource={RelativeSource Self}, Path=Foreground}"/>