問題
在 Xamarin.Forms中,有個 DataTemplateSelector (資料樣板選擇器),請問這是甚麼類別,用來做甚麼用途的呢?
解答
測試範例專案原始碼
在ListView中,若我們想要根據紀錄類型,顯示出不同的樣貌,此時,並不是在 ViewModel 中做處理,而是我們是先定義了多個資料樣板,我們想要透過 DataTemplateSelector (資料樣板選擇器)來根據當時的資料內容,自動幫我們選擇合適的資料樣板;如此,ListView 就可以根據每筆紀錄的內容,顯示出不同的視覺效果了。
在底下的 XAML 範例中,我們在
ContentPage.Resources
中定義了兩個資料樣板 validPersonTemplate
/ invalidPersonTemplate
,另外,也宣告了一個 local:PersonDataTemplateSelector
物件,這個物件是我們自行定義的一個類別,用來根據當時的資料內容,自動傳回合適的資料樣板。<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
xmlns:local="clr-namespace:XFSelector"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="XFSelector.Views.HasSelectorPage">
<ContentPage.Resources>
<ResourceDictionary>
<DataTemplate x:Key="validPersonTemplate">
<ViewCell>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.4*" />
<ColumnDefinition Width="0.3*" />
<ColumnDefinition Width="0.3*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding Name}" TextColor="Green" FontAttributes="Bold" />
<Label Grid.Column="1" Text="{Binding DateOfBirth, StringFormat='{0:d}'}" TextColor="Green" />
<Label Grid.Column="2" Text="{Binding Location}" TextColor="Green" HorizontalTextAlignment="End" />
</Grid>
</ViewCell>
</DataTemplate>
<DataTemplate x:Key="invalidPersonTemplate">
<ViewCell>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.4*" />
<ColumnDefinition Width="0.3*" />
<ColumnDefinition Width="0.3*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding Name}" TextColor="Red" FontAttributes="Bold" />
<Label Grid.Column="1" Text="{Binding DateOfBirth, StringFormat='{0:d}'}" TextColor="Red" />
<Label Grid.Column="2" Text="{Binding Location}" TextColor="Red" HorizontalTextAlignment="End" />
</Grid>
</ViewCell>
</DataTemplate>
<local:PersonDataTemplateSelector
x:Key="personDataTemplateSelector"
ValidTemplate="{StaticResource validPersonTemplate}"
InvalidTemplate="{StaticResource invalidPersonTemplate}" />
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout Padding="20">
<Label Text="有使用資料樣板選擇器" FontAttributes="Bold" HorizontalOptions="Center" />
<ListView
ItemsSource="{Binding People}"
ItemTemplate="{StaticResource personDataTemplateSelector}" />
</StackLayout>
</ContentPage>
接下來,我們來看看 PersonDataTemplateSelector 這個類別要如何定義呢?首先,需要繼承
DataTemplateSelector
這個類別,並且要定義 OnSelectTemplate
這個方法,而我們就會在 OnSelectTemplate
這個方法內,依據當時紀錄的內容,決定要使用哪個資料樣板。 /// <summary>
/// 依據出生日期年分,決定要顯示哪種資料樣板
/// </summary>
public class PersonDataTemplateSelector : DataTemplateSelector
{
// 這個物件值,將會在 XAML 中來定義
public DataTemplate ValidTemplate { get; set; }
// 這個物件值,將會在 XAML 中來定義
public DataTemplate InvalidTemplate { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
// 根據當時物件的值,決定要使用哪個資料樣板
return ((Person)item).DateOfBirth.Year >= 1980 ? ValidTemplate : InvalidTemplate;
}
}