善用 DataTemplateSelector 讓畫面更彈性

善用 DataTemplateSelector 讓畫面更彈性

DataTemplateSelector 在開發 Windows Phone 或 Windows Store App 一定會很常使用到這個技術。

例如:ListView 的每一個 Item 根據值的差異而畫成不同樣子,這時候需要利用 DataTemplateSelector。

 

DataTemplateSelector

     提供一種方法根據 data object 與 data-bound element 來選擇使用的 DataTempalte

主要實作重點有二:

a. 增加一個類別繼承 DataTemplateSelecotr 補上轉換的 SelectTemplate 方法與邏輯

b. XAML 中宣告該 Selector 與支援的 DataTemplate

 

然而是不是什麼都要用到 DataTemplateSeleector 呢?

根據<DataTemplateSelector>的說明:

a. 如果是相同的 data object 中小部分的 properties 不同而有不同的呈現,則建議改用 Data ConverterDataTrigger

b. 如果是相同的 data object 所建立的 datatemplate 也可以指定不同的 data type 來做區格就不需要使用 datatemplateselector。

更多詳細的可參考<Data Templating Overview>的說明。

 

[範例程式]

1. 預期結果;

    2686493684114

    想要呈現二種不同的排版方式,一個是寬版的 size,一個是窄版的 size。

 

2. 建立要使用的 DataTemplateSelector;

public class ContentDataTemplateSelector : DataTemplateSelector
{
    /// <summary>
    /// 寬版的 DataTemplate
    /// </summary>
    public DataTemplate BigSizeTemplate { get; set; }

 
    /// <summary>
    /// 窄版的 DataTemplate
    /// </summary>
    public DataTemplate SmallSizeTemplate { get; set; }

 
    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
    {
        RssItem dataObject = item as RssItem;
        // 利用 dataobject 的 property 來識別
        if (dataObject.StyleType == ItemType.All)
        {
            return BigSizeTemplate;
        }
        else
        {
            return SmallSizeTemplate;
        }
    }
}

 

3. 定義呈現的 XAML 與 DataTemplateSelector;

<Page.Resources>
    <!-- 為 DataTemplateSelector 定義一個 Key -->
    <local:ContentDataTemplateSelector x:Key="contentDataTemplateSelector">
        <!-- 定義寬版的 datatemplate -->
        <local:ContentDataTemplateSelector.BigSizeTemplate>
            <DataTemplate>
                <Grid>
                    <Image Source="{Binding imgUrl}" Stretch="UniformToFill" />
                    <StackPanel Background="Orange" VerticalAlignment="Top" HorizontalAlignment="Left" Width="70">
                        <TextBlock Foreground="White" Text="{Binding category}" Margin="6"
                                   VerticalAlignment="Center" HorizontalAlignment="Center" />
                    </StackPanel>
                    <Grid VerticalAlignment="Bottom" Background="Black" Height="53" Opacity="0.8">
                        <TextBlock Foreground="White" Text="{Binding title}" Margin="3"
                                   FontSize="20" Height="53" TextWrapping="Wrap" VerticalAlignment="Center"
                                   TextTrimming="CharacterEllipsis" />
                    </Grid>
                </Grid>
            </DataTemplate>
        </local:ContentDataTemplateSelector.BigSizeTemplate>
        <!-- 定義窄版的 datatemplate -->
        <local:ContentDataTemplateSelector.SmallSizeTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <Image Grid.Column="0" Source="{Binding imgUrl}" 
                           Stretch="UniformToFill" Height="80" Width="80" />
                    <StackPanel Grid.Column="1" Margin="3,4,0,0">
                        <StackPanel Background="Orange" HorizontalAlignment="Left">
                            <TextBlock Foreground="White" Text="{Binding category}" Margin="6" 
                                       VerticalAlignment="Center" HorizontalAlignment="Center" />
                        </StackPanel>
                        <TextBlock Foreground="White" Text="{Binding title}" Margin="3"
                                   FontSize="18" Height="53" TextWrapping="Wrap" 
                                   VerticalAlignment="Center" TextTrimming="CharacterEllipsis" />
                    </StackPanel>
                </Grid>
            </DataTemplate>
        </local:ContentDataTemplateSelector.SmallSizeTemplate>
    </local:ContentDataTemplateSelector>
</Page.Resources>

 

4. 執行結果:

     99

 

上述的範例如果仔細來分析以,可以看出其實只有 width 的改變,其實可以直接使用 data convert 的機制,

來調整要顯示的大小即可。

 

======

上述主要介紹怎麼實作 DataTemplateSelector,但在使用情境仍需要考量資料量是否太大,

因為 DateTemplateSelector 是 runtime 時才動態調整的,一定沒有事先 compile 來的快速,

所以要多加考量例如藉由將資料切成區塊,每一次只給一小區域範圍等到滑動至置時才載下一個區域。

希望對大家有所幫助,謝謝。

 

References

DataTemplateSelector Class

ContentControl Styles and Templates

Data Templating Overview

WPF Based Dynamic DataTemplateSelector

WPF Tutorial - How To Use A DataTemplateSelector