The BindingContext is one of the most important parts of the Xamarin.Forms data binding system, especially in MVVM applications. Being built into the Binding type as the common source for bindings in a specific scope reduces plumbing code needed and makes XAML more concise. Unfortunately, for any given View there is only one BindingContext available to bind against. For example, you are working with a collection of items using CollectionView. In the DataTemplate of each element you need a Button associated with a Command. However, by default, the BindingContext in the template is an item from the collection. How do we access a Command in the BindingContext of the CollectionView?.
RelativeSource
All of those situations are expressed as relative source modes. RelativeSource has the following modes:
1. Self
Self indicates the element on which the binding is being set, allowing you to bind one property of that element to another property on the same . For example, we want to draw a square using a BoxView. We can do this using the element name:
<BoxView
x:Name="myBoxView"
Color="Red"
HeightRequest="100"
WidthRequest="{Binding Source={x:Reference myBoxView}, Path=HeightRequest}}" />
Alternatively, we can achieve the same result using the RelativeSource:
<BoxView
Color="Red"
HeightRequest="100"
Width="{Binding Source={RelativeSource Self}, Path=HeightRequest}"/>
The FindAncestor relative binding modes are used to bind to parent elements in the visual tree.
<CollectionView
ItemsSource="{Binding Drinks}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid>
...
<Button
Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodels:RelativeSourceViewModel}}, Path=BuyCommand}"
CommandParameter="{Binding Source={RelativeSource Self}, Path=BindingContext}"
... />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
In this example, the BindingContext of the page is set to the RelativeSourceViewModel property of itself. The CollectionView binds to the Drinks property of the viewmodel. The DataTemplate, which defines the appearance of each item in the CollectionView, contains a Button. The button’s Command property is bound to the BuyCommand in its parent’s viewmodel.
The AncestorType property should be set to the type of the element to use as the source.
3. Templated Parent
This mode enables you to tie a given ControlTemplate property to a property of the control that the ControlTemplate is applied to.
To better understand this mode, let’s see an example:
<ControlTemplate x:Key="DrinkCardViewControlTemplate">
<Grid>
<Frame
BindingContext="{Binding Source={RelativeSource TemplatedParent}}">
<StackLayout>
<Label
Text="{Binding DrinkTitle}"
... />
...
</Grid>
</Frame>
</Grid>
</ControlTemplate>
In this example, the Frame, which is the root element of the ControlTemplate, has its BindingContext set to the runtime object instance to which the template is applied. Therefore, the Frame and its children resolve their binding expressions against the properties of each custom control object.
<controls:DrinkCardView
DrinkTitle="BRAZILIAN COFFEE"
DrinkDescription="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
DrinkColor="Maroon"
DrinkImageSource="coffee.png"
ControlTemplate="{StaticResource DrinkCardViewControlTemplate}" />
Hopefully this blog was helpful and showed you how easy it is to use RelativeSource. You can find the sample we have seen in this article and read more about RelativeSource in our amazing documentation.
P1, example 2:
Width=”{Binding RelativeSource={RelativeSource Self}, Path=HeightRequest}”/>
Maybe Source is the correct word?
You’re right Dmytro. It’s already changed.
Great article, I’ve been looking forward to this feature.
From which Xamarin.Forms version is this feature supported?
Hi Reed,
The first version where it was available was 4.3-pre1 https://docs.microsoft.com/en-us/xamarin/xamarin-forms/release-notes/4.3/4.3.0-pre1
Excellent, this is very useful. Now we don’t have to be creating new ViewModels for specific controls in a page.