在 XAML 中使用数据绑定
- 6 分钟
可以使用标记扩展在代码或 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指向Humidity类型上名为WeatherService的属性。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>
使用相同 Path 时不必使用相同的 Source:
<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,该 BindingContext 是在 XAML 中设置的,或者通过代码分配给父元素。 将按照以下模式评估绑定:
如果绑定定义了一个
Source,则使用该源并停止搜索。 将绑定的Path应用于Source以获取值。 如果未设置Source,则会开始查找绑定源。搜索从目标对象本身开始。 如果目标对象的
BindingContext不为 null,则将停止搜索,并将绑定的Path应用于BindingContext以获取值。 如果BindingContext为 null,则会继续搜索。此进程一直持续到它到达 XAML 根为止。 通过检查根的
BindingContext是否为非 null 值来结束搜索。 如果未找到有效的BindingContext,则该绑定没有绑定对象,也不会执行任何操作。
通常在根对象的级别设置 BindingContext,以应用于整个 XAML。
最后还有一个方便的功能值得一提。 绑定会监视对其源的对象引用所做的更改。 这甚至适用于使用 BindingContext 作为源的绑定。 如果将 Source 或 BindingContext 重新分配到其他对象,绑定会捕捉来自新源的数据并更新其目标。