Создание DataTemplateSelector в Xamarin.Forms

С помощью объекта DataTemplateSelector можно выбирать шаблон DataTemplate во время выполнения в соответствии со значением привязанного к данным свойства. Это позволяет применять несколько шаблонов DataTemplate к одному типу объектов, чтобы настроить внешний вид определенных объектов. В этой статье содержатся сведения о создании и использовании объекта 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. Возвращаемый шаблон — это значение свойства ValidTemplate или InvalidTemplate, которые задаются при использовании PersonDataTemplateSelector.

После этого экземпляр класса, представляющего селектор шаблона данных, можно присваивать свойствам элементов управления Xamarin.Forms, таких как ListView.ItemTemplate. Список допустимых свойств см. в статье Создание DataTemplate.

Ограничения

На экземпляры DataTemplateSelector налагаются указанные ниже ограничения.

  • При повторных запросах подкласс DataTemplateSelector должен возвращать один и тот же шаблон для определенных данных.
  • Подкласс DataTemplateSelector не должен возвращать другой подкласс DataTemplateSelector.
  • Подкласс DataTemplateSelector не должен возвращать новые экземпляры DataTemplate при каждом вызове. Должен возвращаться один и тот же экземпляр. В противном случае будет происходить утечка памяти и виртуализация будет отключена.
  • В Android для каждого элемента ListView может быть не более 20 разных шаблонов данных.

Использование DataTemplateSelector в XAML

В 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 на уровне страницы определены два экземпляра DataTemplate и экземпляр PersonDataTemplateSelector. Свойствам ValidTemplate и InvalidTemplate экземпляра PersonDataTemplateSelector присвоены соответствующие экземпляры DataTemplate с помощью расширения разметки StaticResource. Обратите внимание на то, что ресурсы могут определяться не только в объекте ResourceDictionary страницы, но и на уровне элемента управления или приложения.

Экземпляр PersonDataTemplateSelector используется путем присвоения свойству ListView.ItemTemplate, как показано в следующем примере кода.

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

Во время выполнения ListView вызывает метод PersonDataTemplateSelector.OnSelectTemplate для каждого элемента в базовой коллекции. В вызове объект данных передается в качестве параметра item. Затем шаблон DataTemplate, возвращенный методом, применяется к этому объекту.

На следующих снимках экрана показан результат применения PersonDataTemplateSelector к каждому объекту базовой коллекции в ListView.

ListView с селектором шаблона данных

Все объекты Person, свойство DateOfBirth которых имеет значение не меньше 1980, отображаются зеленым цветом. Остальные объекты отображаются красным цветом.

Использование объекта DataTemplateSelector в C#

На 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
      }
    };
  }
  ...  
}

Свойствам ValidTemplate и InvalidTemplate экземпляра PersonDataTemplateSelector присвоены соответствующие экземпляры DataTemplate, созданные методом SetupDataTemplates. Во время выполнения ListView вызывает метод PersonDataTemplateSelector.OnSelectTemplate для каждого элемента в базовой коллекции. В вызове объект данных передается в качестве параметра item. Затем шаблон DataTemplate, возвращенный методом, применяется к этому объекту.

Итоги

В этой статье было показано, как создать и использовать DataTemplateSelector. Объект DataTemplateSelector можно использовать для выбора DataTemplate в среде выполнения на основе значения свойства, привязанного к данным. Это позволяет применять несколько экземпляров DataTemplate к одному типу объектов, чтобы настроить внешний вид определенных объектов.