Основные привязки
Привязка данных .NET Multi-platform App UI (.NET MAUI) связывает пару свойств между двумя объектами, хотя бы одним из которых обычно является объект пользовательского интерфейса. Эти два объекта называются целевым объектом и источником:
- Целевой объект — это объект (и свойство), к которому устанавливается привязка данных.
- Источник — это объект (и свойство), на который ссылается привязка данных.
В самом простом случае данные поступают от источника к целевому объекту, то есть целевое свойство устанавливается на основе значения свойства источника. Однако в некоторых случаях данные могут поступать от целевого объекта к источнику или перемещаться в обоих направлениях.
Внимание
Целевой объект всегда является объектом, на котором задана привязка данных, даже если она предоставляет данные, а не получает данные.
Привязки с контекстом привязки
Рассмотрим следующий пример XAML, намерение которого состоит в повороте:Label Slider
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DataBindingDemos.BasicCodeBindingPage"
Title="Basic Code Binding">
<StackLayout Padding="10, 0">
<Label x:Name="label"
Text="TEXT"
FontSize="48"
HorizontalOptions="Center"
VerticalOptions="Center" />
<Slider x:Name="slider"
Maximum="360"
VerticalOptions="Center" />
</StackLayout>
</ContentPage>
Без привязки данных необходимо настроить событие ValueChanged
объекта Slider в обработчике событий, который обращается к свойству Value
объекта Slider и задает это значение свойству Rotation
объекта Label. Привязка данных автоматизирует эту задачу, поэтому обработчик событий и код в нем больше не требуются.
Вы можете задать привязку к экземпляру любого класса, производного от BindableObject, который включает производные Element, VisualElement, View и View. Привязка всегда настраивается в целевом объекте. Привязка ссылается на исходный объект. Чтобы настроить привязку данных, используйте следующие два члена класса цели.
- Свойство
BindingContext
задает исходный объект. - Метод
SetBinding
указывает целевое свойство и исходное свойство.
В этом примере Label является целевым объектом привязки, а Slider — источником привязки. Изменения в источнике Slider влияют на угол поворота целевого объекта Label. Данные поступают от источника к целевому объекту.
Метод SetBinding
, определенный объектом BindableObject, имеет аргумент типа BindingBase
, из которого производится класс Binding
, но есть другие методы SetBinding
, определенные классом BindableObjectExtensions
. Код для XAML использует более SetBinding
простой метод расширения из BindableObjectExtensions
класса:
public partial class BasicCodeBindingPage : ContentPage
{
public BasicCodeBindingPage()
{
InitializeComponent();
label.BindingContext = slider;
label.SetBinding(Label.RotationProperty, "Value");
}
}
Объект Label является целевым объектом привязки, поэтому на этом объекте устанавливается это свойство и в нем вызывается метод. Свойство BindingContext
указывает источник привязки, то есть Slider. Метод SetBinding
вызывается в целевом объекте привязки, но указывает свойство целевого объекта и свойство источника. Свойство целевого объекта указывается как объект BindableProperty: Label.RotationProperty
. Свойство источника указывается как строка и определяет свойство Value
объекта Slider.
Внимание
целевое свойство должно поддерживаться свойством, подходящим для привязки. Поэтому целевой объект должен быть экземпляром класса, наследуемого от BindableObject. Дополнительные сведения см. в разделе "Привязываемые свойства".
Исходное свойство указывается как строка. На внутреннем уровне используется отражение для доступа к фактическому свойству. В данном случае, однако, свойство Value
также поддерживается привязываемым свойством.
При изменении свойства объекта Slider объект Label поворачивается соответствующим образом:
Кроме того, привязка данных может быть указана в XAML:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DataBindingDemos.BasicXamlBindingPage"
Title="Basic XAML Binding">
<StackLayout Padding="10, 0">
<Label Text="TEXT"
FontSize="80"
HorizontalOptions="Center"
VerticalOptions="Center"
BindingContext="{x:Reference Name=slider}"
Rotation="{Binding Path=Value}" />
<Slider x:Name="slider"
Maximum="360"
VerticalOptions="Center" />
</StackLayout>
</ContentPage>
Как и в коде, привязка данных задается в целевом объекте, то есть Label. Для определения привязки данных используются два расширения разметки XAML:
- Расширение разметки
x:Reference
требуется для ссылки на исходный объект, то есть Slider с именемslider
. - Расширения разметки
Binding
связывает свойствоRotation
объекта Label со свойствомValue
объекта Slider.
Дополнительные сведения о расширениях разметки XAML см. в разделе "Использование расширений разметки XAML".
Примечание.
Исходное свойство указывается со Path
свойством Binding
расширения разметки, которое соответствует Path
свойству Binding
класса.
Расширения разметки XAML, такие как x:Reference
и Binding
, могут иметь определенные атрибуты свойства содержимого. Для расширения разметки XAML это означает, что имя свойства не нужно отображать. Свойство Name
является свойством содержимого x:Reference
, а свойство Path
является свойством содержимого Binding
, то есть их можно удалить из выражения:
<Label Text="TEXT"
FontSize="80"
HorizontalOptions="Center"
VerticalOptions="Center"
BindingContext="{x:Reference slider}"
Rotation="{Binding Value}" />
Внимание
Производительность привязки можно улучшить с помощью скомпилированных привязок. Дополнительные сведения см. в разделе "Скомпилированные привязки".
Привязки без контекста привязки
Свойство BindingContext
является важным компонентом привязок данных, но оно не всегда необходимо. Исходный объект можно указать в вызове SetBinding
или Binding
расширении разметки:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DataBindingDemos.AlternativeCodeBindingPage"
Title="Alternative Code Binding">
<StackLayout Padding="10, 0">
<Label x:Name="label"
Text="TEXT"
FontSize="40"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Slider x:Name="slider"
Minimum="-2"
Maximum="2"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
В этом примере Slider определяется для управления свойством Scale
объекта Label. По этой причине Slider устанавливается диапазон от –2 до 2.
Файл программной части задает привязку с SetBinding
методом, а второй аргумент является конструктором для Binding
класса:
public partial class AlternativeCodeBindingPage : ContentPage
{
public AlternativeCodeBindingPage()
{
InitializeComponent();
label.SetBinding(Label.ScaleProperty, new Binding("Value", source: slider));
}
}
Конструктор Binding
имеет 6 параметров, поэтому параметр source
указан с именованным аргументом. Аргумент является объектом slider
.
Примечание.
Класс VisualElement также определяет свойства ScaleX
и ScaleY
, которые могут масштабировать VisualElement по-разному в горизонтальном и вертикальном направлениях.
Кроме того, привязка данных может быть указана в XAML:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DataBindingDemos.AlternativeXamlBindingPage"
Title="Alternative XAML Binding">
<StackLayout Padding="10, 0">
<Label Text="TEXT"
FontSize="40"
HorizontalOptions="Center"
VerticalOptions="Center"
Scale="{Binding Source={x:Reference slider},
Path=Value}" />
<Slider x:Name="slider"
Minimum="-2"
Maximum="2"
VerticalOptions="Center" />
</StackLayout>
</ContentPage>
В этом примере Binding
расширение разметки имеет два набора свойств и Source
Path
разделено запятой. Свойство Source
задано встроенному расширению разметки x:Reference
, которое в противном случае имеет тот же синтаксис, что и параметр BindingContext
.
Свойство содержимого расширения разметки Binding
— Path
, но часть Path=
расширения разметки можно исключить только в том случае, если это первое свойство в выражении. Чтобы исключить часть Path=
, необходимо поменять два свойства местами:
Scale="{Binding Value, Source={x:Reference slider}}" />
Хотя расширения разметки XAML обычно разделены с помощью фигурных скобок, они также могут быть выражены как элементы объекта:
<Label Text="TEXT"
FontSize="40"
HorizontalOptions="Center"
VerticalOptions="Center">
<Label.Scale>
<Binding Source="{x:Reference slider}"
Path="Value" />
</Label.Scale>
</Label>
В этом примере Source
Path
свойства являются обычными атрибутами XAML. значения заключены в кавычки и атрибуты не разделяются запятыми. Расширение разметки x:Reference
также может стать элементом объекта:
<Label Text="TEXT"
FontSize="40"
HorizontalOptions="Center"
VerticalOptions="Center">
<Label.Scale>
<Binding Path="Value">
<Binding.Source>
<x:Reference Name="slider" />
</Binding.Source>
</Binding>
</Label.Scale>
</Label>
Это нестандартный синтаксис, но иногда он необходим, если используются составные объекты.
Пока в примерах мы задавали свойство BindingContext
и свойство Source
класса Binding
для расширения разметки x:Reference
, чтобы ссылаться на другое представление на странице. Эти два свойства имеют тип Object
, и их можно задать для любого объекта, который содержит свойства, подходящие для источников привязки. Можно также задать BindingContext
расширение разметки или Source
свойство x:Static
, чтобы ссылаться на значение статического свойства или поля, или StaticResource
расширение разметки для ссылки на объект, хранящийся в словаре ресурсов, или непосредственно к объекту, который часто является экземпляром viewmodel.
Примечание.
Свойство BindingContext
также может быть задано для объекта Binding
, чтобы свойства Source
и Path
объекта Binding
определяли контекст привязки.
Наследование контекста привязки
Исходный объект можно указать с помощью BindingContext
свойства или Source
свойства Binding
объекта. Если заданы оба свойства, свойство Source
объекта Binding
имеет приоритет над BindingContext
.
Внимание
BindingContext
Значение свойства наследуется через визуальное дерево.
В следующем примере XAML демонстрируется наследование контекста привязки:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DataBindingDemos.BindingContextInheritancePage"
Title="BindingContext Inheritance">
<StackLayout Padding="10">
<StackLayout VerticalOptions="Fill"
BindingContext="{x:Reference slider}">
<Label Text="TEXT"
FontSize="80"
HorizontalOptions="Center"
VerticalOptions="End"
Rotation="{Binding Value}" />
<BoxView Color="#800000FF"
WidthRequest="180"
HeightRequest="40"
HorizontalOptions="Center"
VerticalOptions="Start"
Rotation="{Binding Value}" />
</StackLayout>
<Slider x:Name="slider"
Maximum="360" />
</StackLayout>
</ContentPage>
В этом примере BindingContext
свойство StackLayout объекта задано slider
. Этот контекст привязки наследуется объектами Label и BoxView, оба из которых имеют свойства Rotation
, зависящие от свойства Value
объекта Slider: