在 XAML 中使用数据绑定
可以使用标记扩展在代码或 XAML 中声明数据绑定。 本单元讨论后者,因为这是创建绑定最常用的方法。 更喜欢使用 XAML 有几点原因。 第一,大多数人将绑定视为 UI 代码的一部分,因为绑定会获取 UI 要显示的数据。 第二,有一个名为 Binding
的标记扩展,易于操作。
什么是数据绑定
绑定将两个属性绑定在一起。 一个属性位于 UI 中,另一个属性位于数据模型对象中。 如果任一属性的值发生更改,绑定对象可以更新另一个属性。 换言之,绑定是同步 UI 和数据的中间对象。 我们使用术语“源”和“目标”来标识所涉及到的两个对象:
源:源可以是任何类型的对象。 在实践中,通常会使用数据对象作为源。 你需要标识该源对象上的属性以参与绑定。 通过在绑定中设置
Path
属性来标识该属性。目标:目标是使用称为
BindableProperty
的特殊属性实现的属性。 具有BindableProperty
的对象必须派生自BindableObject
。 .NET MAUI 中提供的所有控件都派生自BindableObject
,其大部分属性为BindableProperties
。
下图说明了绑定如何成为两个属性之间的中间对象:
如何在 XAML 中创建数据绑定
我们来看看使用 {Binding}
标记扩展在 XAML 创建的简单示例绑定。 它将源的 WeatherService.Humidity
属性绑定到 UI 控件的 Text
属性。
<VerticalStackLayout Margin="10">
<VerticalStackLayout.Resources>
<ResourceDictionary>
<services:WeatherService x:Key="myWeatherService" />
</ResourceDictionary>
</VerticalStackLayout.Resources>
<Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" />
</VerticalStackLayout>
绑定源为:
WeatherService
类型的对象实例。 系统通过{StaticResource ...}
XAML 扩展引用该实例,该扩展指向堆栈布局的资源字典中的对象。Path
指向WeatherService
类型上名为Humidity
的属性。Path
是{Binding}
语法上的第一个未命名参数,可以省略语法Path=
。 这两个绑定是等效的:<Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" /> <Label Text="{Binding Humidity, Source={StaticResource myWeatherService}}" />
绑定目标为:
Label
控件。- 控件的
Text
属性。
显示 UI 时,{Binding}
XAML 扩展会在 WeatherService
和 Label
之间创建绑定。 绑定将 WeatherService.Humidity
属性的值读入 Label.Text
属性。
将另一个控件用作绑定源
绑定的一个有用功能是可以绑定到其他控件。 以下 XAML 是一个简单的演示:
<VerticalStackLayout HorizontalOptions="Center" VerticalOptions="Center">
<Label x:Name="TargetLabel" Text="TEXT TO ROTATE" BackgroundColor="Yellow" />
<Slider WidthRequest="100" Maximum="360"
Value="{Binding Rotation, Mode=OneWayToSource, Source={x:Reference TargetLabel}}" />
</VerticalStackLayout>
Slider.Value
属性绑定到 Label.Rotation
属性,但与之前介绍的方式不同。 此属性使用的是绑定模式 OneWayToSource
,与典型的绑定机制相反。 与“源”更新“目标”相反,OneWayToSource
会在“目标”更改时更新“源”。。 此示例中,当滑块移动时,该绑定模式会根据滑块的值更新标签的旋转,如以下动画所示:
将控件绑定到另一个控件的典型情况是,控件(通常是 ListView
或 CarouselView
等集合控件)有一个要用作数据源的选定项。 在显示天气预报的页面示例中,可能有一个 ListView
显示五天的预报。 当用户在列表中选择一天时,该天气预报的详细信息会显示在其他控件中。 如果用户选择另一天,则其他控件将更新并显示所选日期的详细信息。
跨多个绑定使用相同的源
上一个示例演示了将静态资源用作单个绑定的源。 该源可用于多个绑定。 以下示例跨三个不同的控件声明绑定,这些控件都绑定到同一对象和属性 Path
,但有些控件省略了 Path
属性:
<VerticalStackLayout Margin="10">
<VerticalStackLayout.Resources>
<vm:SimpleWeatherServiceObject x:Key="myWeatherService" />
</VerticalStackLayout.Resources>
<Entry Text="{Binding Humidity, Source={StaticResource myWeatherService}}" />
<Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" />
</VerticalStackLayout>
使用相同 Source
时不必使用相同的 Path
:
<VerticalStackLayout Margin="10">
<VerticalStackLayout.Resources>
<vm:SimpleWeatherServiceObject x:Key="myWeatherService" />
</VerticalStackLayout.Resources>
<Entry Text="{Binding Temperature, Source={StaticResource myWeatherService}}" />
<Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" />
</VerticalStackLayout>
很少会显示来自源的单条数据,但这种情况也有可能发生。 通常会有多个控件使用来自同一源的不同数据片段。 这种情况非常常见,以至于 BindableObject
类具有一个名为 BindingContext
的属性,该属性用作数据绑定的源。 请注意,.NET MAUI 控件继承自 BindableObject
类,因此 .NET MAUI 控件具有 BindingContext
属性。
设置绑定的 Source
是可选项。 未设置 Source
的绑定会自动在 XAML 可视化树中搜索 BindingContext
,它在 XAML 中设置,或通过代码分配给父元素。 将按照以下模式评估绑定:
如果绑定定义了一个
Source
,则使用该源并停止搜索。 将绑定的Path
应用于Source
以获取值。 如果未设置Source
,则会开始查找绑定源。搜索从自身的目标对象开始。 如果目标对象的
BindingContext
不为 null,则将停止搜索,并将绑定的Path
应用于BindingContext
以获取值。 如果BindingContext
为 null,则会继续搜索。此进程一直持续到它到达 XAML 根为止。 将通过检查根目录的
BindingContext
,寻找非 null 值来结束搜索。 如果未找到有效的BindingContext
,则该绑定没有绑定对象,也不会执行任何操作。
通常在根对象的级别设置 BindingContext
,以应用于整个 XAML。
最后还有一个方便的功能值得一提。 绑定会监视对其源的对象引用所做的更改。 它甚至适用于将 BindingContext
用作其源的绑定。 如果将 Source
或 BindingContext
重新分配到其他对象,绑定会捕捉来自新源的数据并更新其目标。