データ テンプレートの選択: プロパティに基づくアイテムのスタイル設定

コレクション コントロールのカスタマイズされた設計は、 DataTemplate によって管理されます。 データ テンプレートは、各項目のレイアウト方法とスタイル設定方法を定義し、そのマークアップをコレクション内のすべての項目に適用します。 この記事では、 DataTemplateSelector を使用してコレクションに異なるデータ テンプレートを適用し、選択した特定の項目プロパティまたは値に基づいて、使用するデータ テンプレートを選択する方法について説明します。

重要な API: DataTemplateSelectorDataTemplate

DataTemplateSelector は、カスタム テンプレート選択ロジックを有効にするクラスです。 これにより、コレクション内の特定の項目に使用するデータ テンプレートを指定するルールを定義できます。 このロジックを実装するには、分離コードで DataTemplateSelector のサブクラスを作成し、項目のカテゴリ (特定の型の項目や特定のプロパティ値を持つ項目など) に使用するデータ テンプレートを決定するロジックを定義します。 このクラスのインスタンスは、XAML ファイルの Resources セクションで、使用するデータ テンプレートの定義と共に宣言します。 これらのリソースは、 x:Key 値を使用して識別します。これにより、XAML でそれらを参照できます。

[前提条件]

DataTemplateSelector を使用しない場合

一般に、ListView または GridView のすべての項目にまったく異なるレイアウト/スタイルを与えるべきではありません。これは DataTemplateSelector の使用が不十分であり、パフォーマンスに悪影響を与えます。

リスト アイテムのビジュアル表示の特定の要素は、特定のプロパティをバインドすることによって、1 つのデータ テンプレートのみを使用して制御できます。 たとえば、データ テンプレート内のアイコン ソース プロパティにバインドし、そのアイコン ソース プロパティに対して各項目に異なる値を与えることで、項目ごとに異なるアイコンを持つことができます。 これにより、DataTemplateSelector を使用するよりもパフォーマンスが向上します。

DataTemplateSelector を使用する場合

1 つのコレクション コントロールで複数のデータ テンプレートを使用する場合は、 DataTemplateSelector を作成する必要があります。 DataTemplateSelectorを使用すると、特定の項目を目立たせながら、同様のレイアウトでアイテムを維持することができます。 DataTemplateSelector が役に立つユース ケースは多数あり、使用しているコントロールと戦略を再考する方が良いシナリオがいくつかあります。

コレクション コントロールは、通常、すべて 1 つの型の項目のコレクションにバインドされます。 ただし、項目が同じ型であっても、特定のプロパティに対して異なる値を持つ場合や、意味が異なる場合があります。 また、特定の項目は他のアイテムよりも重要な場合もあれば、1 つの項目が特に重要または異なる場合があり、視覚的に目立つ必要があります。このような状況では、DataTemplateSelector が非常に役立ちます。

また、さまざまな種類の項目を含むコレクションにバインドすることもできます。バインドされたコレクションには、文字列、int、カスタム クラス オブジェクトなどを混在させることができます。 これにより、DataTemplateSelector は、項目のオブジェクト型に基づいて異なるデータ テンプレートを割り当てることができるので、特に便利です。

データ テンプレート セレクターを使用する場合の例を次に示します。

  • ListView 内で異なるレベルの従業員を表す - 従業員の種類/レベルごとに、異なる色の背景を簡単に区別できるようにする必要がある場合があります。
  • GridView を使用する製品ギャラリー内の販売アイテムを表す - 販売アイテムには、通常の価格のアイテムから目立つように、赤い背景や別の色のフォントが必要な場合があります。
  • FlipView を使用して、フォト ギャラリー内の勝者/上位の写真を表します。
  • ListView で負または正の数値を異なる方法で表す必要がある、または短い文字列/長い文字列。

DataTemplateSelector を作成する

データ テンプレート セレクターを作成するときは、コードでテンプレート選択ロジックを定義し、XAML でデータ テンプレートを定義します。

コードビハインド コンポーネント

データ テンプレート セレクターを使用するには、まず、分離コードで DataTemplateSelector (そこから派生するクラス) のサブクラスを作成します。 クラスでは、各テンプレートをクラスのプロパティとして宣言します。 次に、 SelectTemplateCore メソッドをオーバーライドして、独自のテンプレート選択ロジックを含めます。

DataTemplateSelectorと呼ばれる単純なMyDataTemplateSelector サブクラスの例を次に示します。

public class MyDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate Normal { get; set; }
    public DataTemplate Accent { get; set; }

    protected override DataTemplate SelectTemplateCore(object item)
    {
        if ((int)item % 2 == 0)
        {
            return Normal;
        }
        else
        {
            return Accent;
        }
    }
}

MyDataTemplateSelector クラスは、DataTemplateSelector クラスから派生し、最初に 2 つの DataTemplate オブジェクト (NormalAccent) を定義します。 ここでは、これらは空の宣言ですが、XAML ファイル内のマークアップで "入力" されます。

SelectTemplateCore メソッドは、項目オブジェクト (つまり、各コレクション項目) を受け取り、特定の状況に応じてどのDataTemplateを返すかを決定する規則でオーバーライドされます。 この場合、項目が奇数の場合は、 Accent データ テンプレートを受け取り、偶数の場合は Normal データ テンプレートを受け取ります。

XAML コンポーネント

次に、XAML ファイルの Resources セクションで、この新しい MyDataTemplateSelector クラスのインスタンスを作成する必要があります。 すべてのリソースには、x:Key が必要です。これは、後の手順でコレクション コントロールのItemTemplateSelector プロパティにバインドするために使用します。 また、 DataTemplate オブジェクトの 2 つのインスタンスを作成し、それらのレイアウトを resources セクションで定義します。 これらのデータ テンプレートは、Accent クラスで宣言したNormalプロパティとMyDataTemplateSelectorプロパティに割り当てます。

必要な XAML リソースとマークアップの例を次に示します。

<Page.Resources>

<DataTemplate x:Key="NormalItemTemplate" x:DataType="x:Int32">
    <Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{ThemeResource SystemChromeLowColor}">
        <TextBlock Text="{x:Bind}" />
    </Button>
</DataTemplate>

<DataTemplate x:Key="AccentItemTemplate" x:DataType="x:Int32">
    <Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{ThemeResource SystemAccentColor}">
        <TextBlock Text="{x:Bind}" />
    </Button>
</DataTemplate>

<l:MyDataTemplateSelector x:Key="MyDataTemplateSelector"
    Normal="{StaticResource NormalItemTemplate}"
    Accent="{StaticResource AccentItemTemplate}"/>

</Page.Resources>

前述のように、2 つのデータ テンプレート NormalAccent が定義されています。項目は両方ともボタンとして表示されますが、 Accent データ テンプレートでは背景にアクセント カラー ブラシが使用されますが、 Normal データ テンプレートでは灰色のカラー ブラシ (SystemChromeLowColor) が使用されます。 次に、これら 2 つのデータ テンプレートが、C# 分離コードで作成された MyDataTemplateSelector クラスの属性である Normal および Accent DataTemplate オブジェクトに割り当てられます。

最後の手順では、 DataTemplateSelector をコレクション コントロールの ItemTemplateSelector プロパティ (この場合は ListView) にバインドします。 これにより、 ItemTemplate プロパティに値を割り当てる必要性が置き換わります。

<ListView x:Name = "TestListView"
          ItemsSource = "{x:Bind NumbersList}"
          ItemTemplateSelector = "{StaticResource MyDataTemplateSelector}">
</ListView>

コードがコンパイルされると、各コレクション項目は、SelectTemplateCoreでオーバーライドされたMyDataTemplateSelector メソッドを介して実行され、適切な DataTemplate でレンダリングされます。

Important

DataTemplateSelectorを使用する場合は、DataTemplateSelectorItemTemplate プロパティにバインドします。 ItemsRepeater には ItemTemplateSelector プロパティがありません。

DataTemplateSelector のパフォーマンスに関する考慮事項

ListView または GridView を大規模なデータ コレクションと共に使用する場合、スクロールとパンのパフォーマンスが問題になる可能性があります。 大規模なコレクションのパフォーマンスを維持するために、データ テンプレートのパフォーマンスを向上させるために実行できるいくつかの手順があります。 詳細については、 ListView と GridView UI の最適化に関する説明を参照してください。

  • 項目ごとの要素の削減 - データ テンプレート内の UI 要素の数を妥当な最小値に保ちます。
  • 異種コレクションを使用したコンテナーのリサイクル
    • ChoosingItemContainer イベントを使用する - このイベントは、項目ごとに異なるデータ テンプレートを使用する高パフォーマンスの方法です。 最適なパフォーマンスを実現するには、キャッシュを最適化し、特定のデータのデータ テンプレートを選択する必要があります。
    • 項目テンプレート セレクターを使用する - 項目テンプレート セレクター (DataTemplateSelector) は、パフォーマンスへの影響のため、一部のインスタンスでは回避する必要があります。