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 속성 값입니다.

그런 다음 데이터 템플릿 선택기 클래스의 인스턴스는 Xamarin.Forms 컨트롤 속성(예: ListView.ItemTemplate)에 할당할 수 있습니다. 유효한 속성 목록은 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는 두 개의 DataTemplate 인스턴스와 한 개의 PersonDataTemplateSelector 인스턴스를 정의합니다. PersonDataTemplateSelector 인스턴스는 StaticResource 태그 확장을 사용하여 해당 ValidTemplateInvalidTemplate 속성을 적절한 DataTemplate 인스턴스로 설정합니다. 리소스는 페이지의 ResourceDictionary에 정의되지만 컨트롤 수준이나 애플리케이션 수준에서도 정의될 수 있습니다.

PersonDataTemplateSelector 인스턴스는 다음 코드 예제와 같이 ListView.ItemTemplate 속성에 할당하여 사용합니다.

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

런타임 시 ListView는 기본 컬렉션의 각 항목에 대해 PersonDataTemplateSelector.OnSelectTemplate 메서드를 호출하며, 호출 시 데이터 개체를 item 매개 변수로 전달합니다. 그런 다음, 메서드에서 반환된 DataTemplate이 해당 개체에 적용됩니다.

다음 스크린샷은 기본 컬렉션의 각 개체에 PersonDataTemplateSelector를 적용한 ListView의 결과를 보여 줍니다.

데이터 템플릿 선택기를 사용하는 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 인스턴스는 해당 ValidTemplateInvalidTemplate 속성을 SetupDataTemplates 메서드로 만든 적절한 DataTemplate 인스턴스로 설정합니다. 런타임 시 ListView는 기본 컬렉션의 각 항목에 대해 PersonDataTemplateSelector.OnSelectTemplate 메서드를 호출하며, 호출 시 데이터 개체를 item 매개 변수로 전달합니다. 그런 다음, 메서드에서 반환된 DataTemplate이 해당 개체에 적용됩니다.

요약

이 문서에서는 DataTemplateSelector를 만들고 사용하는 방법을 보여줍니다. DataTemplateSelector는 데이터 바인딩된 속성의 값에 기반하여 런타임 시 DataTemplate을 선택하는 데 사용됩니다. 이렇게 하면 여러 DataTemplate 인스턴스를 같은 유형의 개체에 적용하여 특정 개체의 모양을 사용자 지정할 수 있습니다.