MAUI新生3.4-深入理解XAML:数据模板DataTemplate
数据模板主要作用是定义集合类控件的数据显示外观,和前面几个章节自定义控件的关系不大。数据模板本质上是定义集合的每一个迭代对象的UI,和Vue的v-for或Blazor的foreach类似。数据模板可以直接在控件内部定义(内联数据模板),也可以定义在控件级、页面级或应用级的资源字典中。
一、内联 数据模板的定义和使用
<ContentPage ...... xmlns:model="clr-namespace:MauiApp10.Models"> <VerticalStackLayout> <CollectionView> <!--属性ItemsSource设置数据源,使用泛型Array<T>集合--> <CollectionView.ItemsSource> <x:Array Type="{x:Type model:Employee}"> <model:Employee Id="1" Name="zs" EntryDate="2021-01-01" /> <model:Employee Id="2" Name="ls" EntryDate="2021-05-01" /> <model:Employee Id="3" Name="ww" EntryDate="2021-07-01" /> </x:Array> </CollectionView.ItemsSource> <!--属性ItemTemplate设置数据模板,Item指迭代集合的每一行--> <CollectionView.ItemTemplate> <DataTemplate> <Grid ColumnDefinitions="1*,2*,3*"> <Label Grid.Column="0" HorizontalOptions="Center" Text="{Binding Id}" /> <Label Grid.Column="1" HorizontalOptions="Center" Text="{Binding Name}" /> <Label Grid.Column="2" HorizontalOptions="Center" Text="{Binding EntryDate}" /> </Grid> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView> </VerticalStackLayout> </ContentPage>
二、资源字典 数据模板的定义和使用
<ContentPage ...... xmlns:model="clr-namespace:MauiApp10.Models"> <!--定义页面级资源字典--> <ContentPage.Resources> <ResourceDictionary> <DataTemplate x:Key="employeeTemplate"> <Grid ColumnDefinitions="1*,2*,3*"> <Label Grid.Column="0" HorizontalOptions="Center" Text="{Binding Id}" /> <Label Grid.Column="1" HorizontalOptions="Center" Text="{Binding Name}" /> <Label Grid.Column="2" HorizontalOptions="Center" Text="{Binding EntryDate}" /> </Grid> </DataTemplate> </ResourceDictionary> </ContentPage.Resources> <VerticalStackLayout> <!--直接设置ItemTemplate属性,引用静态资源--> <CollectionView ItemTemplate="{StaticResource employeeTemplate}"> <CollectionView.ItemsSource> <x:Array Type="{x:Type model:Employee}"> <model:Employee Id="1" Name="zs" EntryDate="2021-01-01" /> <model:Employee Id="2" Name="ls" EntryDate="2021-05-01" /> <model:Employee Id="3" Name="ww" EntryDate="2021-07-01" /> </x:Array> </CollectionView.ItemsSource> </CollectionView> </VerticalStackLayout> </ContentPage>
三、控件模板也可以作为数据模板使用
<!--控件模板--> <ContentView ......> <Grid ColumnDefinitions="1*,2*,3*"> <Label Grid.Column="0" HorizontalOptions="Center" Text="{Binding Id}" /> <Label Grid.Column="1" HorizontalOptions="Center" Text="{Binding Name}" /> <Label Grid.Column="2" HorizontalOptions="Center" Text="{Binding EntryDate}" /> </Grid> </ContentView> <!--DataTemplate为控件模板实例化对象--> <CollectionView> <CollectionView.ItemsSource> ...... </CollectionView.ItemsSource> <CollectionView.ItemTemplate> <DataTemplate> <control:EmployeeView /> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView>
四、使用DataTemplateSelector(数据模板选择器),根据条件更改Item行样式。类似于在Vue或Blazor的循环中使用的if,但XAML使用for或者if会麻烦非常多,这也是XAML被诟病的地方。以下直接扒文档案例。
1、第一步,定义数据模板选择器类,派生自DataTemplateSelector
public class PersonDataTemplateSelector : DataTemplateSelector { //定义两个数据模板属性 public DataTemplate ValidTemplate { get; set; } public DataTemplate InvalidTemplate { get; set; } //参数item为集合控件的迭代对象,参数container为集合控件对象 protected override DataTemplate OnSelectTemplate(object item, BindableObject container) { //返回值为数据模板 //根据出生日期,使用不同的数据模板 return ((Person)item).DateOfBirth.Year >= 1980 ? ValidTemplate : InvalidTemplate; } }
2、第二步,在资源字典中定义数据模板和数据模板选择器
<ContentPage.Resources> <!--定义数据模板validPersonTemplate--> <DataTemplate x:Key="validPersonTemplate"> ... </DataTemplate> <!--定义数据模板invalidPersonTemplate--> <DataTemplate x:Key="invalidPersonTemplate"> ... </DataTemplate> <!--实例化数据模板选择器对象--> <local:PersonDataTemplateSelector x:Key="personDataTemplateSelector" ValidTemplate="{StaticResource validPersonTemplate}" InvalidTemplate="{StaticResource invalidPersonTemplate}" /> </ContentPage.Resources>
3、第三步,使用数据模板选择器
<CollectionView ItemTemplate="{StaticResource personDataTemplateSelector}" .../>