浏览示例
.NET Multi-platform App UI (.NET MAUI) 数据绑定在两个对象之间链接一对属性,其中至少一个对象通常是用户界面对象。 这两个对象称为“目标”和“源”:
- “目标”是用来设置数据绑定的对象(以及属性)。
- 源是数据绑定引用的对象(和属性)。
在最简单的情况下,数据从源流到目标,这意味着目标属性值是从源属性的值设置的。 但是,在某些情况下,数据也可以从目标流向源,或者双向流动。
重要
目标始终是在其上设置数据绑定的对象,即使它提供数据而不接收数据也是如此。
带有绑定上下文的绑定
请考虑以下 XAML 示例,其目的是通过操作 Slider 来旋转 Label:
<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>
在没有数据绑定的情况下,你可以为 Slider 的 ValueChanged 事件设置一个事件处理程序,该处理程序访问 Slider 的 Value 属性,并将该值设置为 Label 的 Rotation 属性。 数据绑定会自动执行此任务,因此不再需要事件处理程序及其中的代码。
可以在派生自 BindableObject 的任何类的实例上设置绑定,这些类包括 Element、VisualElement、View 和其他派生项。 绑定始终在目标对象上进行设置。 绑定引用源对象。 要设置数据绑定,请使用目标类的以下两个成员:
-
BindingContext属性指定源对象。 -
SetBinding方法指定目标属性和源属性。
在本例中,Label 是绑定目标,Slider 是绑定源。 更改 Slider 源会影响 Label 目标的旋转。 数据从源流向目标。
在代码中编写的绑定有时使用字符串路径,这些路径在运行时通过反射进行解析。 但是,SetBinding 扩展方法也提供了一个重载,该重载使用 Func 参数来定义绑定:
public partial class BasicCodeBindingPage : ContentPage
{
public BasicCodeBindingPage()
{
InitializeComponent();
label.BindingContext = slider;
label.SetBinding(Label.RotationProperty, static (Slider slider) => slider.Value);
}
}
Label 对象是绑定目标,因此它是设置此属性和调用该方法的对象。 参数 Func 指示绑定源,即 Slider.
SetBinding 方法在绑定目标上被调用,但需同时指定目标属性和源属性。 目标属性被指定为一个 BindableProperty 对象:Label.RotationProperty。 源属性是使用 lambda 表达式指定的,并表示 Slider 的 Value 属性。
重要
目标属性必须由可绑定属性支持。 因此,目标对象必须是从 BindableObject 派生的类的一个实例。 有关详细信息,请参阅可绑定属性。
在上面的示例中,绑定源是使用 a Func指定的,这可确保为提高运行时性能编译绑定表达式。 有关已编译绑定的详细信息,请参阅 已编译绑定。
基本代码绑定。
或者,可以在 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 x:DataType="Slider"
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标记扩展将 Label 的Rotation属性链接到 Slider 的Value属性。
有关 XAML 标记扩展的更多信息,请参阅使用 XAML 标记扩展。
此外,位于Label上的x:DataType属性指示XAML编译器编译Label上的绑定表达式以提升运行时性能,并指定该绑定表达式应针对Slider类型进行解析。 有关详细信息,请参阅已编译绑定。
注意
源属性由 Path 标记扩展的 Binding 属性指定,它对应于 Path 类的 Binding 属性。
XAML 标记扩展(如 x:Reference 和 Binding)可以定义“内容属性”,对于 XAML 标记扩展,这意味着属性名称不需要出现。
Name 属性是 x:Reference 的内容属性,Path 属性是 Binding 的内容属性,这意味着可以从表达式中省略它们:
<Label x:DataType="Slider"
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="Center" />
<Slider x:Name="slider"
Minimum="-2"
Maximum="2"
VerticalOptions="Center" />
</StackLayout>
</ContentPage>
在此示例中,Slider 被定义以控制 Label 的 Scale 属性。 因此,将滑块的范围设置为-2到2。
代码隐藏文件使用 SetBinding 方法来设置绑定,第二个参数 Func 用于获取 Slider 的值。
public partial class AlternativeCodeBindingPage : ContentPage
{
public AlternativeCodeBindingPage()
{
InitializeComponent();
label.SetBinding(Label.ScaleProperty, static (Slider s) => s.Value, 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 x:DataType='Slider',
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}, x:DataType='Slider'}" />
尽管 XAML 标记扩展通常由大括号分隔,但它们也可以表示为对象元素:
<Label Text="TEXT"
FontSize="40"
HorizontalOptions="Center"
VerticalOptions="Center">
<Label.Scale>
<Binding x:DataType="Slider"
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 x:DataType="Slider"
Path="Value">
<Binding.Source>
<x:Reference Name="slider" />
</Binding.Source>
</Binding>
</Label.Scale>
</Label>
这种语法并不常见,但当涉及到复杂对象时,有时它也是必要的。
到目前为止显示的示例将 BindingContext 属性和 Source 属性设置为 x:Reference 标记扩展,用于引用页面上的其他视图。 这两个属性的类型是 Object,可以将它们设置为包含适合作为数据源绑定的属性的任何对象。 还可以将 BindingContext 或 Source 属性设置为 x:Static 标记扩展,以引用静态属性或字段的值,或将 StaticResource 标记扩展用于引用存储在资源字典中的对象,或者直接设置为对象,而这对象通常是视图模型的实例。
注意
还可以将 BindingContext 属性设置为 Binding 对象,以便 Binding 的 Source 和 Path 属性定义绑定上下文。
绑定上下文继承
可以使用 BindingContext 属性或 Source 属性来指定 Binding 对象的源对象。 如果两者都已设置,则 Source 属性优先于 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 x:DataType="Slider"
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属性都设置为Slider的Value属性:
绑定上下文继承。