相关文章推荐

.NET 多平台应用 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>
    

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

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

  • 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 标记扩展

    使用标记扩展的 属性指定Path源属性,该属性与 Path 类的 Binding 属性相对Binding应。

    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 属性是数据绑定的重要组件,但并不总是必要的。 可以改为在调用或Binding标记扩展中SetBinding指定源对象:

    <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 定义为控制 ScaleLabel属性。 因此, 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,可以将它们设置为包含适合绑定源的属性的任何对象。 还可以将 或 Source 属性设置为BindingContextx:Static标记扩展以引用静态属性或字段的值,或StaticResource将标记扩展设置为引用存储在资源字典中的对象,或直接设置为对象(通常是 viewmodel 的实例)。

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

    绑定上下文继承

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

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

     
    推荐文章