XamarinForms 系列課程

特別說明

2017/02/19

Xamarin FAQ 2-19 : 在ListView中,如何根據紀錄類型,顯示出不同的樣貌(資料樣板選擇器)

問題

在 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;
        }
    }
Xamarin-跨平台手機應用程式設計入門-粉絲團

沒有留言:

張貼留言