Относительные привязки Xamarin.Forms
Относительные привязки позволяют задать источник привязки относительно положения целевого объекта привязки. Они создаются с помощью расширения разметки RelativeSource
и задаются в качестве свойства Source
выражения привязки.
Расширение разметки RelativeSource
поддерживается классом RelativeSourceExtension
, определяющим следующие свойства:
Mode
с типомRelativeBindingSourceMode
описывает расположение источника привязки относительно положения целевого объекта привязки.AncestorLevel
с типомint
является необязательным уровнем предка для поиска, когда свойствоMode
имеет значениеFindAncestor
.AncestorLevel
n
пропускаетn-1
экземплярыAncestorType
.AncestorType
с типомType
является типом предка для поиска, когда свойствоMode
имеет значениеFindAncestor
.
Примечание.
Средство синтаксического анализа XAML позволяет сократить класс RelativeSourceExtension
как RelativeSource
.
Для свойства Mode
должен быть задан один из членов перечисления RelativeBindingSourceMode
.
TemplatedParent
указывает элемент, к которому применяется шаблон, где существует связанный элемент. Дополнительные сведения см. в разделе Привязка к шаблонному родительскому элементу.Self
указывает элемент, в котором настраивается привязка, позволяя привязать одно свойство этого элемента к другому свойству того же элемента. Дополнительные сведения см. в разделе Привязка к самому себе.FindAncestor
указывает предка в визуальном дереве связанного элемента. Этот режим следует использовать для привязки к элементу управления предка, представленному свойствомAncestorType
. Дополнительные сведения см. в разделе Привязка к предку.FindAncestorBindingContext
указываетBindingContext
предка в визуальном дереве связанного элемента. Этот режим следует использовать для привязки кBindingContext
предка, представленному свойствомAncestorType
. Дополнительные сведения см. в разделе Привязка к предку.
Свойство Mode
— это свойство содержимого класса RelativeSourceExtension
. Таким образом, для выражений разметки XAML с фигурными скобками можно исключить часть Mode=
выражения.
Дополнительные сведения о расширениях разметки Xamarin.Forms см. в статье Расширения разметки XAML.
Привязка к самому себе
Режим относительной привязки Self
используется для привязки свойства элемента к другому свойству того же элемента:
<BoxView Color="Red"
WidthRequest="200"
HeightRequest="{Binding Source={RelativeSource Self}, Path=WidthRequest}"
HorizontalOptions="Center" />
В этом примере BoxView
задает для своего свойства WidthRequest
фиксированный размер, а свойство HeightRequest
привязывается к свойству WidthRequest
. Таким образом, оба свойства равны, поэтому рисуется квадрат:
Внимание
При привязке свойства элемента к другому свойству того же элемента эти свойства должны иметь одинаковый тип. Кроме того, в привязке можно указать преобразователь для преобразования значения.
Обычно этот режим привязки используется для того, чтобы задать для BindingContext
объекта его же свойство. В приведенном ниже коде показан соответствующий пример:
<ContentPage ...
BindingContext="{Binding Source={RelativeSource Self}, Path=DefaultViewModel}">
<StackLayout>
<ListView ItemsSource="{Binding Employees}">
...
</ListView>
</StackLayout>
</ContentPage>
В этом примере для BindingContext
страницы задается его собственное свойство DefaultViewModel
. Это свойство определено в файле кода программной части для страницы и предоставляет экземпляр модели представления. ListView
привязывается к свойству Employees
модели представления.
Привязка к предку
Режимы относительной привязки FindAncestor
и FindAncestorBindingContext
используются для привязки к родительским элементам определенного типа в визуальном дереве. Режим FindAncestor
используется для привязки к родительскому элементу, производному от типа Element
. Режим FindAncestorBindingContext
используется для привязки к BindingContext
родительского элемента.
Предупреждение
При использовании режимов относительной привязки FindAncestor
и FindAncestorBindingContext
необходимо задать Type
для свойства AncestorType
, в противном случае возникает исключение XamlParseException
.
Если свойство Mode
не задано явным образом, задание для свойства AncestorType
типа, производного от Element
, неявно назначит свойству Mode
значение FindAncestor
. Аналогичным образом, задание для свойства AncestorType
типа, не являющегося производным от Element
, неявно назначит свойству Mode
значение FindAncestorBindingContext
.
Примечание.
Относительные привязки, использующие режим FindAncestorBindingContext
, будут повторно применены при изменении BindingContext
любых предков.
В следующем коде XAML показан пример, где для свойства Mode
будет неявно задано значение FindAncestorBindingContext
:
<ContentPage ...
BindingContext="{Binding Source={RelativeSource Self}, Path=DefaultViewModel}">
<StackLayout>
<ListView ItemsSource="{Binding Employees}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Label Text="{Binding Fullname}"
VerticalOptions="Center" />
<Button Text="Delete"
Command="{Binding Source={RelativeSource AncestorType={x:Type local:PeopleViewModel}}, Path=DeleteEmployeeCommand}"
CommandParameter="{Binding}"
HorizontalOptions="EndAndExpand" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
В этом примере для BindingContext
страницы задается его собственное свойство DefaultViewModel
. Это свойство определено в файле кода программной части для страницы и предоставляет экземпляр модели представления. ListView
привязывается к свойству Employees
модели представления. DataTemplate
, определяющий внешний вид каждого элемента в ListView
, содержит Button
. Свойство Command
кнопки привязано к DeleteEmployeeCommand
в модели представления его родительского элемента. При нажатии Button
удаляется сотрудник:
Кроме того, необязательное свойство AncestorLevel
может помочь устранить неоднозначность поиска предка в случаях, где в визуальном дереве может существовать более одного предка данного типа:
<Label Text="{Binding Source={RelativeSource AncestorType={x:Type Entry}, AncestorLevel=2}, Path=Text}" />
В этом примере свойство Label.Text
привязывается к свойству Text
второго Entry
, обнаруженному на пути вверх, начиная с целевого объекта привязки.
Примечание.
Свойству AncestorLevel
должно быть назначено значение 1, чтобы найти предка, ближайшего к целевому объекту привязки.
Привязка к шаблонному родительскому элементу
Режим относительной привязки TemplatedParent
используется для привязки из шаблона элемента управления к экземпляру объекта среды выполнения, к которому применяется этот шаблон (также называется шаблонным родительским элементом). Этот режим применим только в том случае, если относительная привязка находится внутри шаблона элемента управления и аналогична заданию TemplateBinding
.
Ниже представлен пример XAML для относительной привязки TemplatedParent
:
<ContentPage ...>
<ContentPage.Resources>
<ControlTemplate x:Key="CardViewControlTemplate">
<Frame BindingContext="{Binding Source={RelativeSource TemplatedParent}}"
BackgroundColor="{Binding CardColor}"
BorderColor="{Binding BorderColor}"
...>
<Grid>
...
<Label Text="{Binding CardTitle}"
... />
<BoxView BackgroundColor="{Binding BorderColor}"
... />
<Label Text="{Binding CardDescription}"
... />
</Grid>
</Frame>
</ControlTemplate>
</ContentPage.Resources>
<StackLayout>
<controls:CardView BorderColor="DarkGray"
CardTitle="John Doe"
CardDescription="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla elit dolor, convallis non interdum."
IconBackgroundColor="SlateGray"
IconImageSource="user.png"
ControlTemplate="{StaticResource CardViewControlTemplate}" />
<controls:CardView BorderColor="DarkGray"
CardTitle="Jane Doe"
CardDescription="Phasellus eu convallis mi. In tempus augue eu dignissim fermentum. Morbi ut lacus vitae eros lacinia."
IconBackgroundColor="SlateGray"
IconImageSource="user.png"
ControlTemplate="{StaticResource CardViewControlTemplate}" />
<controls:CardView BorderColor="DarkGray"
CardTitle="Xamarin Monkey"
CardDescription="Aliquam sagittis, odio lacinia fermentum dictum, mi erat scelerisque erat, quis aliquet arcu."
IconBackgroundColor="SlateGray"
IconImageSource="user.png"
ControlTemplate="{StaticResource CardViewControlTemplate}" />
</StackLayout>
</ContentPage>
В этом примере Frame
, являющийся корневым элементом ControlTemplate
, имеет BindingContext
, для которого установлен экземпляр объекта среды выполнения, к которому применяется шаблон. Таким образом, Frame
и его дочерние элементы разрешают свои выражения привязки для свойств каждого объекта CardView
:
Дополнительные сведения о шаблонах элементов управления см. в разделе Шаблоны элементов управления Xamarin.Forms.