Xamarin.Forms DataTemplateSelector の作成

DataTemplateSelector を使用して、データバインド プロパティの値に基づいて、実行時に DataTemplate を選択できます。 これにより、複数の DataTemplates を同じ種類のオブジェクトに適用し、特定のオブジェクトの外観をカスタマイズできます。 この記事では、DataTemplateSelector を作成して使用する方法を示します。

データ テンプレート セレクターによって、オブジェクトのコレクションにバインドされる ListView などのシナリオが可能になります。この場合、ListView 内の各オブジェクトの外観は、特定の DataTemplate を返すデータ テンプレート セレクターによって実行時に選択できます。

DataTemplateSelector の作成

データ テンプレート セレクターを実装するには、DataTemplateSelector から継承するクラスを作成します。 次のコード例に示すように、OnSelectTemplate メソッドがオーバーライドされ、特定の DataTemplate が返されます。

public class PersonDataTemplateSelector : DataTemplateSelector
{
  public DataTemplate ValidTemplate { get; set; }
  public DataTemplate InvalidTemplate { get; set; }

  protected override DataTemplate OnSelectTemplate (object item, BindableObject container)
  {
    return ((Person)item).DateOfBirth.Year >= 1980 ? ValidTemplate : InvalidTemplate;
  }
}

OnSelectTemplate メソッドからは、DateOfBirth プロパティの値に基づいて適切なテンプレートが返されます。 返されるテンプレートは、PersonDataTemplateSelector の使用時に設定される ValidTemplate プロパティまたは InvalidTemplate プロパティの値です。

データ テンプレート セレクター クラスのインスタンスは、ListView.ItemTemplate などの Xamarin.Forms コントロール プロパティに割り当てることができます。 有効なプロパティの一覧については、DataTemplate の作成に関するページを参照してください。

制限事項

DataTemplateSelector インスタンスには次の制限事項があります。

  • 複数回クエリが実行された場合、同じデータに対して DataTemplateSelector サブクラスからは常に同じテンプレートが返される必要があります。
  • DataTemplateSelector サブクラスから別の DataTemplateSelector サブクラスを返すことはできません。
  • 呼び出しごとに、DataTemplateSelector サブクラスから新しいインスタンスの DataTemplate を返すことはできません。 代わりに、同じインスタンスを返す必要があります。 そうしないと、メモリ リークが発生し、仮想化が無効になります。
  • Android では、ListView ごとに使用できるデータ テンプレートは 20 種類以下です。

XAML での DataTemplateSelector の使用

XAML で PersonDataTemplateSelector をインスタンス化するには、次のコード例のようにリソースとして宣言します。

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:Selector;assembly=Selector" x:Class="Selector.HomePage">
    <ContentPage.Resources>
        <ResourceDictionary>
            <DataTemplate x:Key="validPersonTemplate">
                <ViewCell>
                   ...
                </ViewCell>
            </DataTemplate>
            <DataTemplate x:Key="invalidPersonTemplate">
                <ViewCell>
                   ...
                </ViewCell>
            </DataTemplate>
            <local:PersonDataTemplateSelector x:Key="personDataTemplateSelector"
                ValidTemplate="{StaticResource validPersonTemplate}"
                InvalidTemplate="{StaticResource invalidPersonTemplate}" />
        </ResourceDictionary>
    </ContentPage.Resources>
  ...
</ContentPage>

このページ レベルの ResourceDictionary には、2 つの DataTemplate インスタンスと 1 つの PersonDataTemplateSelector インスタンスが定義されています。 PersonDataTemplateSelector インスタンスでは、StaticResource マークアップ拡張を使用して、ValidTemplate および InvalidTemplate プロパティが適切な DataTemplate インスタンスに設定されます。 リソースはページの ResourceDictionary に定義されていますが、コントロール レベルまたはアプリケーション レベルで定義することもできる点に注意してください。

PersonDataTemplateSelector インスタンスを使用するには、次のコード例に示すように、ListView.ItemTemplate プロパティに割り当てます。

<ListView x:Name="listView" ItemTemplate="{StaticResource personDataTemplateSelector}" />

実行時に、基となるコレクション内の項目ごとに、ListView から PersonDataTemplateSelector.OnSelectTemplate メソッドが呼び出されます。このとき、呼び出しでデータ オブジェクトが item パラメーターとして渡されます。 このメソッドから返された DataTemplate はそのオブジェクトに適用されます。

次のスクリーンショットは、ListView によって、基となるコレクション内の各オブジェクトに対して PersonDataTemplateSelector が適用された結果を示しています。

データ テンプレート セレクターを使用する ListView

DateOfBirth プロパティ値が 1980 以上のすべての Person オブジェクトは緑色で表示され、その他のオブジェクトは赤色で表示されます。

C# での DataTemplateSelector の使用

次のコード例に示すように、C# では、PersonDataTemplateSelector をインスタンス化して ListView.ItemTemplate プロパティに割り当てることができます。

public class HomePageCS : ContentPage
{
  DataTemplate validTemplate;
  DataTemplate invalidTemplate;

  public HomePageCS ()
  {
    ...
    SetupDataTemplates ();
    var listView = new ListView {
      ItemsSource = people,
      ItemTemplate = new PersonDataTemplateSelector {
        ValidTemplate = validTemplate,
        InvalidTemplate = invalidTemplate }
    };

    Content = new StackLayout {
      Margin = new Thickness (20),
      Children = {
        ...
        listView
      }
    };
  }
  ...  
}

PersonDataTemplateSelector インスタンスでは、SetupDataTemplates メソッドで作成された適切な DataTemplate インスタンスに ValidTemplate および InvalidTemplate プロパティが設定されます。 実行時に、基となるコレクション内の項目ごとに、ListView から PersonDataTemplateSelector.OnSelectTemplate メソッドが呼び出されます。このとき、呼び出しでデータ オブジェクトが item パラメーターとして渡されます。 このメソッドから返された DataTemplate はそのオブジェクトに適用されます。

まとめ

この記事では、DataTemplateSelector を作成して使用する方法について説明しました。 DataTemplateSelector を使用すると、データバインド プロパティの値に基づいて実行時に DataTemplate を選択できます。 これにより、複数の DataTemplate インスタンスを同じ種類のオブジェクトに適用し、特定のオブジェクトの外観をカスタマイズできます。