.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>
如果没有数据绑定,你可以将 Slider 的 ValueChanged
事件设置为访问 Slider 的 Value
属性的事件处理程序,并将该值设置为 Label 的 Rotation
属性。 数据绑定自动执行此任务,因此不再需要事件处理程序和其中的代码。
可以在派生自 BindableObject的任何类的实例上设置绑定,其中包括 Element、VisualElementView、 和 View 派生类。 绑定始终在目标对象上进行设置。 绑定引用源对象。 要设置数据绑定,请使用目标类的以下两个成员:
BindingContext
属性指定源对象。
SetBinding
方法指定目标属性和源属性。
在本例中,Label 是绑定目标,Slider 是绑定源。 Slider 源中的更改会影响 Label 目标的旋转。 数据从源流向目标。
BindableObject 定义的 SetBinding
方法的参数类型为 BindingBase
,Binding
类从该类派生而来,但 BindableObjectExtensions
类还定义了其他 SetBinding
方法。 XAML 的代码隐藏使用 类中的BindableObjectExtensions
更简单SetBinding
的扩展方法:
public partial class BasicCodeBindingPage : ContentPage
public BasicCodeBindingPage()
InitializeComponent();
label.BindingContext = slider;
label.SetBinding(Label.RotationProperty, "Value");
Label 对象是绑定目标,因此它是设置该属性和调用该方法的对象。 BindingContext
属性指示绑定源 Slider。 SetBinding
方法在绑定目标上进行调用,但需同时指定目标属性和源属性。 目标属性指定为 BindableProperty 对象:Label.RotationProperty
。 源属性指定为字符串,并指示 Slider 的 Value
属性。
目标属性必须由可绑定属性支持。 因此,目标对象必须是派生自 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 标记扩展用于定义数据绑定:
引用源对象(命名为 slider
的 Slider)需要 x:Reference
标记扩展。
Binding
标记扩展将 Label 的 Rotation
属性链接到 Slider 的 Value
属性。
有关 XAML 标记扩展的详细信息,请参阅 使用 XAML 标记扩展。
使用标记扩展的 属性指定Path
源属性,该属性与 Path
类的 Binding
属性相对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
属性是数据绑定的重要组件,但并不总是必要的。 可以改为在调用或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 定义为控制 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>
这种语法并不常见,但当涉及到复杂对象时,有时它也是必要的。
到目前为止显示的示例将 Binding
的 BindingContext
属性和 Source
属性设置为 x:Reference
标记扩展,以引用页面上的另一个视图。 这两个属性的类型是 Object
,可以将它们设置为包含适合绑定源的属性的任何对象。 还可以将 或 Source
属性设置为BindingContext
x:Static
标记扩展以引用静态属性或字段的值,或StaticResource
将标记扩展设置为引用存储在资源字典中的对象,或直接设置为对象(通常是 viewmodel 的实例)。
还可以将 BindingContext
属性设置为 Binding
对象,以便 Binding
的 Source
和 Path
属性定义绑定上下文。
绑定上下文继承
可以使用 对象的 BindingContext
属性或 Source
属性 Binding
指定源对象。 如果两者都已设置,则 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 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
属性: