基本绑定

浏览示例。 浏览示例

.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>

如果没有数据绑定,你可以将 SliderValueChanged 事件设置为访问 SliderValue 属性的事件处理程序,并将该值设置为 LabelRotation 属性。 数据绑定会自动执行此任务,因此不再需要事件处理程序及其中的代码。

可以在派生自 BindableObject 的任何类的实例上设置绑定,这些类包括 ElementVisualElementViewView 派生物。 绑定始终在目标对象上进行设置。 绑定引用源对象。 要设置数据绑定,请使用目标类的以下两个成员:

  • BindingContext 属性指定源对象。
  • SetBinding 方法指定目标属性和源属性。

在本例中,Label 是绑定目标,Slider 是绑定源。 Slider 源中的更改会影响 Label 目标的旋转。 数据从源流向目标。

BindableObject 定义的 SetBinding 方法的参数类型为 BindingBaseBinding 类从该类派生而来,但 BindableObjectExtensions 类还定义了其他 SetBinding 方法。 XAML 的代码隐藏使用 BindableObjectExtensions 类中更简单的 SetBinding 扩展方法:

public partial class BasicCodeBindingPage : ContentPage
{
    public BasicCodeBindingPage()
    {
        InitializeComponent();

        label.BindingContext = slider;
        label.SetBinding(Label.RotationProperty, "Value");
    }
}

Label 对象是绑定目标,因此它是设置该属性和调用该方法的对象。 BindingContext 属性指示绑定源 SliderSetBinding 方法在绑定目标上进行调用,但需同时指定目标属性和源属性。 目标属性指定为 BindableProperty 对象:Label.RotationProperty。 源属性指定为字符串,并指示 SliderValue 属性。

重要

目标属性必须由可绑定属性支持。 因此,目标对象必须是派生自 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 标记扩展可用于定义数据绑定:

  • 引用源对象(命名为 sliderSlider)需要 x:Reference 标记扩展。
  • Binding 标记扩展将 LabelRotation 属性链接到 SliderValue 属性。

有关 XAML 标记扩展的详细信息,请参阅使用 XAML 标记扩展

注意

源属性由 Binding 标记扩展的 Path 属性指定,它对应于 Binding 类的 Path 属性。

XAML 标记扩展名(如 x:ReferenceBinding)可以定义“内容属性”属性,对于 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 来控制 LabelScale 属性。 因此,将 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 类还定义了 ScaleXScaleY 属性,这些属性可以在水平和垂直方向上以不同方式缩放 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 标记扩展设置了两个属性,即 SourcePath,用逗号分隔。 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>

在此示例中,SourcePath 属性是常规 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>

这种语法并不常见,但当涉及到复杂对象时,有时它也是必要的。

到目前为止显示的示例将 BindingBindingContext 属性和 Source 属性设置为 x:Reference 标记扩展,以引用页面上的另一个视图。 这两个属性的类型是 Object,可以将它们设置为包含适合绑定源的属性的任何对象。 还可以将 BindingContextSource 属性设置为 x:Static 标记扩展以引用静态属性或字段的值,或将 StaticResource 标记扩展设置为引用存储在资源字典中的对象,或直接设置为通常是 viewmodel 实例的对象。

注意

还可以将 BindingContext 属性设置为 Binding 对象,以便 BindingSourcePath 属性定义绑定上下文。

绑定上下文继承

可以使用 Binding 对象的 BindingContext 属性或 Source 属性指定源对象。 如果两者都已设置,则 BindingSource 属性优先于 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>

在此示例中,StackLayoutBindingContext 属性被设置为 slider 对象。 该绑定上下文由 LabelBoxView 继承,它们的 Rotation 属性都设置为 SliderValue 属性:

绑定上下文继承。