Содержание
Относительная привязка (relative binding) позволяет задавать источник привязки относительно положения целевого объекта в визуальном дереве элементов. Относительные привязки задаются с использованием расширения разметки RelativeSource
.
Свойства RelativeSource
В RelativeSource
могут использоваться следующие свойства:
Свойство | Тип | Описание |
Mode |
RelativeBindingSourceMode |
Режим относительной привязки. Может принимать следующие значения:
|
AncestorLevel |
int |
Уровень элементов в визуальном дереве относительно контейнера, где будет вестись поиск объекта-источника привязки (используется, если свойство Mode имеет значение FindAncestor ) |
AncestorType |
Type |
Определяет тип элементов, среди которых будет производиться поиск объекта-источника привязки (используется, если свойство Mode имеет значение FindAncestor ) |
Рассмотрим как можно использовать относительную привязку в своих приложениях .NET MAUI.
Привязка к самому себе (Mode=Self)
Это наиболее простой режим относительной привязки. Например, напишем следующий код XAML:
<VerticalStackLayout Padding="30,0" Spacing="25"> <BoxView WidthRequest="{Binding Source={x:Reference WidthSlider}, Path=Value}" HeightRequest="{Binding Source={RelativeSource Mode=Self}, Path=WidthRequest}"/> <Slider Maximum="500" Minimum="10" x:Name="WidthSlider"></Slider> </VerticalStackLayout>
Здесь свойство WidthRequest
элемента BoxView
привязано к значению Value
слайдера WidthSlider
. Здесь мы используем обычную привязку. В свою очередь свойство HeightRequest
привязывается к самом себе, а именно — к свойству WidthRequest
. Таким образом, и ширина и высота BoxView
будут меняться одинаково при изменении значения Value
и слайдера:
Относительная привязка к предку (Mode=FindAncestor и Mode=FindAncestorBindingContext)
Режимы FindAncestor
и FindAncestorBindingContext
используются для привязки к родительским элементам в визуальном дереве. При этом родительский элемент не обязательно должен быть контейнером компоновки.
Режим FindAncestor
используется для привязки к родительскому элементу, производному от типа Element
, а FindAncestorBindingContext
— для привязки к свойству BindingContext
родительского элемента. Если при установке привязки свойство Mode
явным образом, то возможны два варианта поведения:
- если свойство
AncestorType
в качестве значения получает объект, производный отElement
, то свойствоMode
неявно получает значениеFindAncestor
- если свойство
AncestorType
в качестве значения получает объект, не являющийся наследником от Element, то свойствоMode
неявно получает значениеFindAncestorBindingContext
Например, рассмотрим следующий код:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="MauiApp14.MainPage" xmlns:local ="clr-namespace:MauiApp14"> <ContentPage.Resources> <ResourceDictionary> <local:SizeConverter x:Key="SizeConverter"/> </ResourceDictionary> </ContentPage.Resources> <ScrollView> <VerticalStackLayout Padding="30,0" Spacing="25"> <Border WidthRequest="{Binding Source={x:Reference HeightSlider}, Path=Value}" HeightRequest="{Binding Source={RelativeSource Mode=Self}, Path=WidthRequest}" Background="Green"> <BoxView HeightRequest="{Binding Source={RelativeSource AncestorType={x:Type Border}}, Path=HeightRequest, Converter={StaticResource SizeConverter}}" WidthRequest="{Binding Source={RelativeSource AncestorType={x:Type Border}}, Path=HeightRequest, Converter={StaticResource SizeConverter}}" Color="Red"></BoxView> </Border> <Slider Maximum="500" Minimum="10" x:Name="HeightSlider"></Slider> </VerticalStackLayout> </ScrollView> </ContentPage>
Здесь SizeConverter
— это конвертер значений, который выглядит следующим образом:
class SizeConverter : IValueConverter { public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { return (double)value - 20; } public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) { throw new NotImplementedException(); } }
Что касается визуальных элементов, то здесь элемент Border
является родительским элементом для BoxView
:
<Border ....> <BoxView .....></BoxView> </Border>
Как и в предыдущем примере с BoxView
, у Border
свойство ширины привязано к значению Value
слайдера, а высоты — к самому себе. Что касается BoxView
, то для его свойств установлены две относительные привязки к родителю, то есть к Border
:
<BoxView HeightRequest="{Binding Source={RelativeSource AncestorType={x:Type Border}}, Path=HeightRequest, Converter={StaticResource SizeConverter}}" WidthRequest="{Binding Source={RelativeSource AncestorType={x:Type Border}}, Path=HeightRequest, Converter={StaticResource SizeConverter}}" Color="Red"> </BoxView>
Таким образом, так как Mode
в относительной привязке явно не указано, то будет использоваться режим FindAncestor
. Теперь можно запустить приложение и убедиться, что оба элемента синхронно изменяют свои размеры:
Итого
Относительная привязка в .NET MAUI позволяет привязываться к объектам и их свойствам относительно положения целевого объекта в визуальном дереве. Используя относительную привязку мы можем привязываться либо к самом себе, либо к родительским элементам.