데이터 템플릿 개요

WPF 데이터 템플릿 모델을 사용하면 데이터의 표현 방법을 매우 융통성 있게 정의할 수 있습니다. WPF 컨트롤에는 데이터 표현을 사용자 지정할 수 있도록 지원하는 기능이 기본적으로 포함되어 있습니다. 이 항목에서는 먼저 DataTemplate을 정의하는 방법을 보여 준 다음 사용자 지정 논리를 기반으로 한 템플릿 선택, 계층적 데이터 표시에 대한 지원 등 데이터 템플릿이 제공하는 다른 기능을 소개합니다.

이 항목에는 다음 단원이 포함되어 있습니다.

  • 사전 요구 사항
  • 데이터 템플릿 기본 사항
  • DataTemplate에 요소 추가
  • 데이터 개체의 속성을 기준으로 DataTemplate 선택
  • ItemsControl에 스타일 및 템플릿 적용
  • 계층적 데이터 지원
  • 관련 항목

사전 요구 사항

이 항목에서는 데이터 템플릿 기능에 중점을 두고 설명하며 데이터 바인딩 개념에 대해서는 다루지 않습니다. 데이터 바인딩의 기본 개념에 대한 자세한 내용은 데이터 바인딩 개요를 참조하십시오.

DataTemplate은 데이터의 표현과 관련된 기능을 지원하며 이것은 WPF 스타일 및 템플릿 모델이 제공하는 많은 기능 중 하나입니다. Style을 사용하여 컨트롤에 속성을 설정하는 방법을 비롯해 WPF 스타일 및 템플릿 모델에 대한 소개를 보려면 스타일 지정 및 템플릿 항목을 참조하십시오.

기본적으로 StyleDataTemplate과 같은 개체를 다시 사용할 수 있게 하는 Resources에 대해서도 정확하게 이해하고 있어야 합니다. 리소스에 대한 자세한 내용은 리소스 개요를 참조하십시오.

데이터 템플릿 기본 사항

이 단원에는 다음 하위 단원이 포함되어 있습니다.

  • DataTemplate을 사용하지 않은 경우
  • 간단한 DataTemplate 정의
  • DataTemplate을 리소스로 만들기
  • DataType 속성

이제 데이터 바인딩 예제를 단계별로 살펴봄으로써 DataTemplate이 왜 중요한지에 대해 알아보겠습니다. 이 예제에서는 Task 개체 목록에 바인딩된 ListBox를 사용합니다. 각 Task 개체에는 TaskName(string), Description(string) 및 Priority(int)와 TaskType 형식의 속성이 있습니다. 이 속성은 Home 및 Work라는 값을 가진 Enum입니다.

<Window x:Class="SDKSample.Window1"
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="clr-namespace:SDKSample"
  Title="Introduction to Data Templating Sample">
  <Window.Resources>
    <local:Tasks x:Key="myTodoList"/>


...



</Window.Resources>
  <StackPanel>
    <TextBlock Name="blah" FontSize="20" Text="My Task List:"/>
    <ListBox Width="400" Margin="10"
             ItemsSource="{Binding Source={StaticResource myTodoList}}"/>


...


  </StackPanel>
</Window>

DataTemplate을 사용하지 않은 경우

DataTemplate을 사용하지 않은 경우에는 ListBox의 모양이 다음과 같습니다.

데이터 템플릿 샘플 스크린 샷

구체적으로 지정된 사항이 없는 경우 ListBox는 컬렉션의 개체를 표시하려고 할 때 기본적으로 ToString을 호출하는 것을 알 수 있습니다. 따라서 Task 개체가 ToString 메서드를 재정의하면 ListBox는 기본 컬렉션에 있는 각 소스 개체의 문자열 표현을 표시합니다.

예를 들어 Task 클래스가 이러한 방법으로 ToString 메서드를 재정의한다고 가정해 보십시오. 여기서 name은 TaskName 속성에 대한 필드입니다.

Public Overrides Function ToString() As String
    Return _name.ToString()
End Function
public override string ToString()
{
    return name.ToString();
}

그러면 ListBox의 모양이 다음과 같습니다.

데이터 템플릿 샘플 스크린 샷

하지만 여기에는 제한이 따르고 융통성도 적습니다. 또한 XML 데이터에 바인딩하는 경우에는 ToString을 재정의할 수 없는 문제도 있습니다.

간단한 DataTemplate 정의

DataTemplate을 정의하면 이러한 문제를 해결할 수 있습니다. DataTemplate은 ListBoxItemTemplate 속성을 DataTemplate로 설정하는 방법으로 정의할 수 있습니다. DataTemplate에 지정한 내용에 따라 데이터 개체의 시각적 구조가 결정됩니다. 다음 DataTemplate은 매우 간단한 형태입니다. 이 예제에서는 각 항목이 StackPanel 내에 세 개의 TextBlock 요소로 나타나도록 지정합니다. 각 TextBlock 요소는 Task 클래스의 속성에 바인딩되어 있습니다.

<ListBox Width="400" Margin="10"
         ItemsSource="{Binding Source={StaticResource myTodoList}}">
   <ListBox.ItemTemplate>
     <DataTemplate>
       <StackPanel>
         <TextBlock Text="{Binding Path=TaskName}" />
         <TextBlock Text="{Binding Path=Description}"/>
         <TextBlock Text="{Binding Path=Priority}"/>
       </StackPanel>
     </DataTemplate>
   </ListBox.ItemTemplate>
 </ListBox>

이 항목의 예제에 사용된 기본 데이터는 CLR 개체의 컬렉션입니다. XML 데이터에 바인딩하는 경우 기본 개념은 같지만 구문이 약간 다릅니다. 예를 들어 Path=TaskName을 사용하는 대신 XPath를 @TaskName으로 설정해야 합니다(TaskName이 XML 노드의 특성인 경우).

이제 ListBox의 모양이 다음과 같습니다.

데이터 템플릿 샘플 스크린 샷

DataTemplate을 리소스로 만들기

위의 예제에서는 DataTemplate이 인라인으로 정의되어 있지만, 개체를 다시 사용할 수 있도록 다음 예제와 같이 리소스 섹션에 정의하는 경우가 보다 일반적입니다.

<Window.Resources>


...


<DataTemplate x:Key="myTaskTemplate">
  <StackPanel>
    <TextBlock Text="{Binding Path=TaskName}" />
    <TextBlock Text="{Binding Path=Description}"/>
    <TextBlock Text="{Binding Path=Priority}"/>
  </StackPanel>
</DataTemplate>


...


</Window.Resources>

이제 다음 예제와 같이 myTaskTemplate을 리소스로 사용할 수 있습니다.

<ListBox Width="400" Margin="10"
         ItemsSource="{Binding Source={StaticResource myTodoList}}"
         ItemTemplate="{StaticResource myTaskTemplate}"/>

myTaskTemplate은 리소스이므로 DataTemplate 형식을 사용하는 속성을 가진 다른 컨트롤에 사용할 수 있습니다. 앞에서 볼 수 있듯이 ListBox와 같은 ItemsControl 개체의 경우에는 ItemTemplate 속성이 여기에 해당하고, ContentControl 개체의 경우에는 ContentTemplate 속성이 여기에 해당합니다.

DataType 속성

DataTemplate 클래스에는 Style 클래스의 TargetType 속성과 매우 유사한 DataType 속성이 있습니다. 따라서 앞의 예제처럼 DataTemplate에 대해 x:Key를 지정하는 대신 다음과 같이 지정할 수 있습니다.

<DataTemplate DataType="{x:Type local:Task}">
  <StackPanel>
    <TextBlock Text="{Binding Path=TaskName}" />
    <TextBlock Text="{Binding Path=Description}"/>
    <TextBlock Text="{Binding Path=Priority}"/>
  </StackPanel>
</DataTemplate>

DataTemplate은 모든 Task 개체에 자동으로 적용됩니다. 여기서 x:Key는 암시적으로 설정된다는 점에 유의해야 합니다. 따라서 이 DataTemplate에 x:Key 값을 할당하면 암시적 x:Key가 재정의되어 DataTemplate이 자동으로 적용되지 않게 됩니다.

ContentControl을 Task 개체의 컬렉션에 바인딩하는 경우 ContentControl이 위의 DataTemplate을 자동으로 사용하지 않는다는 점에도 유의해야 합니다. 이는 ContentControl에서의 바인딩의 경우 바인딩할 항목이 전체 컬렉션인지 아니면 개별 개체인지 구분하기 위해 추가 정보가 필요하기 때문입니다. ContentControlItemsControl 형식의 선택을 추적하는 경우 ContentControl 바인딩의 Path 속성을 "/"로 설정하여 현재 항목을 바인딩하려는 것임을 나타낼 수 있습니다. 예제를 보려면 방법: 선택에 따라 수집 및 표시 정보에 바인딩을 참조하십시오. 그렇지 않은 경우에는 ContentTemplate 속성을 설정하여 DataTemplate을 명시적으로 지정해야 합니다.

DataType 속성은 다양한 형식의 데이터 개체로 구성된 CompositeCollection을 사용할 때 특히 유용합니다. 예제를 보려면 방법: CompositeCollection 구현을 참조하십시오.

DataTemplate에 요소 추가

현재로서도 데이터가 필요한 정보와 함께 표시되지만 좀 더 개선할 수 있는 부분이 있습니다. Border, Grid, 그리고 표시되는 데이터에 대해 설명하는 몇 가지 TextBlock 요소를 추가하여 데이터가 더 세련되게 나타나도록 만들어 보겠습니다.


<DataTemplate x:Key="myTaskTemplate">
  <Border Name="border" BorderBrush="Aqua" BorderThickness="1"
          Padding="5" Margin="5">
    <Grid>
      <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
        <RowDefinition/>
      </Grid.RowDefinitions>
      <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
      </Grid.ColumnDefinitions>
      <TextBlock Grid.Row="0" Grid.Column="0" Text="Task Name:"/>
      <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=TaskName}" />
      <TextBlock Grid.Row="1" Grid.Column="0" Text="Description:"/>
      <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=Description}"/>
      <TextBlock Grid.Row="2" Grid.Column="0" Text="Priority:"/>
      <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=Priority}"/>
    </Grid>
  </Border>


...


</DataTemplate>

다음 스크린 샷에서는 수정된 DataTemplate이 적용된 ListBox를 보여 줍니다.

데이터 템플릿 샘플 스크린 샷

항목 너비가 전체 공간을 차지하도록 ListBox에 대해 HorizontalContentAlignmentStretch로 설정할 수 있습니다.

<ListBox Width="400" Margin="10"
     ItemsSource="{Binding Source={StaticResource myTodoList}}"
     ItemTemplate="{StaticResource myTaskTemplate}" 
     HorizontalContentAlignment="Stretch"/>

HorizontalContentAlignment 속성을 Stretch로 설정하면 ListBox의 모양이 다음과 같습니다.

데이터 템플릿 샘플 스크린 샷

DataTrigger를 사용하여 속성 값 적용

현재 데이터 표현으로는 Task가 재택 작업인지 사무실 작업인지 알 수 없습니다. Task 개체에는 TaskType 형식의 TaskType 속성이 있으며, 이 속성은 Home 및 Work라는 값을 가진 열거형이므로 이를 이용하여 작업을 구분할 수 있습니다.

다음 예제에서는 TaskType 속성이 TaskType.Home인 경우 DataTrigger가 border라는 요소의 BorderBrush를 Yellow로 설정합니다.

<DataTemplate x:Key="myTaskTemplate">


...


<DataTemplate.Triggers>
  <DataTrigger Binding="{Binding Path=TaskType}">
    <DataTrigger.Value>
      <local:TaskType>Home</local:TaskType>
    </DataTrigger.Value>
    <Setter TargetName="border" Property="BorderBrush" Value="Yellow"/>
  </DataTrigger>
</DataTemplate.Triggers>


...


</DataTemplate>

이와 같이 적용한 결과 이제 모양이 다음과 같습니다. 재택 작업에는 노란색 테두리가, 사무실 작업에는 바다색 테두리가 적용되어 나타납니다.

데이터 템플릿 샘플 스크린 샷

이 예제에서는 DataTriggerSetter를 사용하여 속성 값을 설정합니다. 트리거 클래스에는 애니메이션과 같은 작업 집합을 시작하는 데 사용할 수 있는 EnterActionsExitActions 속성도 있습니다. 또한 데이터 바인딩된 여러 개의 속성 값을 기준으로 변경 내용을 적용하는 데 사용할 수 있는 MultiDataTrigger 클래스도 있습니다.

BorderBrush 속성을 TaskType 속성에 바인딩한 다음 값 변환기를 사용하여 TaskType 값을 기준으로 색을 반환하는 방법을 사용해도 같은 효과를 얻을 수 있습니다. 변환기를 사용하여 위와 같은 효과를 만들어내면 성능 면에서 보다 효율적입니다. 뿐만 아니라 고유의 변환기를 만들면 고유의 논리를 제공할 수 있으므로 보다 많은 융통성을 발휘할 수 있습니다. 사용자의 환경과 선호하는 사항에 따라 사용할 방법을 선택하는 것이 좋습니다. 변환기를 작성하는 자세한 방법은 IValueConverter를 참조하십시오.

DataTemplate에 포함되는 사항

앞의 예제에서는 DataTemplate.Triggers 속성을 사용하여 DataTemplate 내에 트리거를 배치했습니다. 트리거의 Setter 속성이 DataTemplate.내에 있는 요소(Border 요소)의 속성 값을 설정했습니다. 하지만 Setters와 관련된 속성이 현재 DataTemplate 내에 있는 요소의 속성이 아닌 경우에는 ListBoxItem 클래스에 대한 Style을 사용하여 속성을 설정하는 것이 적합합니다(바인딩하는 컨트롤이 ListBox인 경우). 예를 들어 마우스가 항목을 가리킬 때 Trigger가 항목의 Opacity 값에 애니메이션 효과를 주도록 하려면 ListBoxItem 스타일 내에 트리거를 정의합니다. 예제를 보려면 Introduction to Styling and Templating 샘플을 참조하십시오.

DataTemplate은 일반적으로 생성된 각 ListBoxItem에 적용된다는 점에 유의하십시오. 실제로 적용되는 방법 및 위치에 대한 자세한 내용은 ItemTemplate 페이지를 참조하십시오. DataTemplate은 데이터 개체의 표현 및 모양과만 관련됩니다. 대부분의 경우, 항목이 선택될 때의 항목의 모양 또는 ListBox에 항목이 배치되는 방법과 같은 데이터 표현의 다른 모든 측면은 DataTemplate의 정의에 포함되지 않습니다. 예제를 보려면 ItemsControl에 스타일 및 템플릿 적용 단원을 참조하십시오.

데이터 개체의 속성을 기준으로 DataTemplate 선택

DataType 속성 단원에서는 다양한 데이터 개체에 대해 서로 다른 데이터 템플릿을 정의할 수 있다는 점에 대해 설명했습니다. 이는 다양한 형식이 포함된 CompositeCollection 또는 다양한 형식의 항목이 포함된 컬렉션을 사용할 때 특히 유용합니다. DataTrigger를 사용하여 속성 값 적용 단원에서는 동일한 형식의 데이터 개체가 포함된 컬렉션을 사용하는 경우 DataTemplate을 만든 다음 트리거를 사용하여 각 데이터 개체의 속성 값에 따라 변경 내용을 적용할 수 있다는 것을 보여 주었습니다. 하지만 트리거를 사용할 경우 속성 값을 적용하거나 애니메이션을 시작할 수는 있지만 데이터 개체의 구조를 다시 만들 수는 없습니다. 형식은 같지만 속성이 다른 여러 데이터 개체에 대해 서로 다른 DataTemplate을 만들어야 하는 경우도 있습니다.

예를 들어 Task 개체의 Priority 값이 1인 경우 해당 작업에 대해 주의를 환기시킬 수 있도록 이 개체를 완전히 다른 모양으로 나타내려는 경우가 있습니다. 이 경우 우선 순위가 높은 Task 개체를 표시하는 데 사용할 DataTemplate을 만듭니다. Resources 섹션에 다음 DataTemplate을 추가해 보겠습니다.

<DataTemplate x:Key="importantTaskTemplate">
  <DataTemplate.Resources>
    <Style TargetType="TextBlock">
      <Setter Property="FontSize" Value="20"/>
    </Style>
  </DataTemplate.Resources>
  <Border Name="border" BorderBrush="Red" BorderThickness="1"
          Padding="5" Margin="5">
    <DockPanel HorizontalAlignment="Center">
      <TextBlock Text="{Binding Path=Description}" />
      <TextBlock>!</TextBlock>
    </DockPanel>
  </Border>
</DataTemplate>

이 예제에서는 DataTemplate.Resources 속성을 사용합니다. Resources 섹션에 정의된 리소스는 DataTemplate 내의 요소들이 공유합니다.

데이터 개체의 Priority 값에 따라 사용할 DataTemplate을 선택하는 논리를 제공하려면 DataTemplateSelector의 서브클래스를 만들고 SelectTemplate 메서드를 재정의합니다. 다음 예제에서 SelectTemplate 메서드는 Priority 속성 값에 따라 적절한 템플릿을 반환하는 논리를 제공합니다. 상위 Window 요소의 리소스에서 반환할 템플릿을 찾습니다.


Namespace SDKSample
    Public Class TaskListDataTemplateSelector
        Inherits DataTemplateSelector
        Public Overrides Function SelectTemplate(ByVal item As Object, ByVal container As DependencyObject) As DataTemplate

            Dim element As FrameworkElement
            element = TryCast(container, FrameworkElement)

            If element IsNot Nothing AndAlso item IsNot Nothing AndAlso TypeOf item Is Task Then

                Dim taskitem As Task = TryCast(item, Task)

                If taskitem.Priority = 1 Then
                    Return TryCast(element.FindResource("importantTaskTemplate"), DataTemplate)
                Else
                    Return TryCast(element.FindResource("myTaskTemplate"), DataTemplate)
                End If
            End If

            Return Nothing
        End Function
    End Class
End Namespace
using System.Windows;
using System.Windows.Controls;

namespace SDKSample
{
    public class TaskListDataTemplateSelector : DataTemplateSelector
    {
        public override DataTemplate
            SelectTemplate(object item, DependencyObject container)
        {
            FrameworkElement element = container as FrameworkElement;

            if (element != null && item != null && item is Task)
            {
                Task taskitem = item as Task;

                if (taskitem.Priority == 1)
                    return
                        element.FindResource("importantTaskTemplate") as DataTemplate;
                else
                    return
                        element.FindResource("myTaskTemplate") as DataTemplate;
            }

            return null;
        }
    }
}

그런 다음 TaskListDataTemplateSelector를 리소스로 선언할 수 있습니다.

<Window.Resources>


...


<local:TaskListDataTemplateSelector x:Key="myDataTemplateSelector"/>


...


</Window.Resources>

템플릿 선택기 리소스를 사용하려면 해당 리소스를 ListBoxItemTemplateSelector 속성에 할당합니다. ListBox는 기본 컬렉션에 있는 각 항목에 대해 TaskListDataTemplateSelector의 SelectTemplate 메서드를 호출합니다. 이 호출을 통해 데이터 개체가 항목 매개 변수로 전달됩니다. 그런 다음 메서드에서 반환되는 DataTemplate은 해당 데이터 개체에 적용됩니다.

<ListBox Width="400" Margin="10"
         ItemsSource="{Binding Source={StaticResource myTodoList}}"
         ItemTemplateSelector="{StaticResource myDataTemplateSelector}"
         HorizontalContentAlignment="Stretch"/>

템플릿 선택기가 배치되어 이제 ListBox의 모양이 다음과 같습니다.

데이터 템플릿 샘플 스크린 샷

이것으로 이 예제에 대한 설명을 마치겠습니다. 전체 샘플을 보려면 Introduction to Data Templating 샘플을 참조하십시오.

ItemsControl에 스타일 및 템플릿 적용

DataTemplate을 사용할 수 있는 컨트롤 형식이 ItemsControl뿐인 것은 아니지만 컬렉션에 ItemsControl을 바인딩하는 것은 가장 많이 사용되는 시나리오입니다. DataTemplate에 포함되는 사항 단원에서는 DataTemplate에 대한 정의가 데이터의 표현과만 관련된다는 점에 대해 설명했습니다. ItemsControl이 제공하는 다양한 스타일과 템플릿 속성에 대해 이해하고 있으면 어느 경우에 DataTemplate을 사용하는 것이 적합하지 않은지를 알 수 있습니다. 다음 예제에서는 이러한 각 속성의 기능을 보여 줍니다. 이 예제의 ItemsControl은 앞의 예제와 같은 Tasks 컬렉션에 바인딩되어 있습니다. 이해를 돕기 위해 이 예제에서는 모든 스타일과 템플릿이 인라인으로 선언됩니다.

<ItemsControl Margin="10"
              ItemsSource="{Binding Source={StaticResource myTodoList}}">
  <!--The ItemsControl has no default visual appearance.
      Use the Template property to specify a ControlTemplate to define
      the appearance of an ItemsControl. The ItemsPresenter uses the specified
      ItemsPanelTemplate (see below) to layout the items. If an
      ItemsPanelTemplate is not specified, the default is used. (For ItemsControl,
      the default is an ItemsPanelTemplate that specifies a StackPanel.-->
  <ItemsControl.Template>
    <ControlTemplate TargetType="ItemsControl">
      <Border BorderBrush="Aqua" BorderThickness="1" CornerRadius="15">
        <ItemsPresenter/>
      </Border>
    </ControlTemplate>
  </ItemsControl.Template>
  <!--Use the ItemsPanel property to specify an ItemsPanelTemplate
      that defines the panel that is used to hold the generated items.
      In other words, use this property if you want to affect
      how the items are laid out.-->
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <WrapPanel />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
  <!--Use the ItemTemplate to set a DataTemplate to define
      the visualization of the data objects. This DataTemplate
      specifies that each data object appears with the Proriity
      and TaskName on top of a silver ellipse.-->
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <DataTemplate.Resources>
        <Style TargetType="TextBlock">
          <Setter Property="FontSize" Value="18"/>
          <Setter Property="HorizontalAlignment" Value="Center"/>
        </Style>
      </DataTemplate.Resources>
      <Grid>
        <Ellipse Fill="Silver"/>
        <StackPanel>
          <TextBlock Margin="3,3,3,0"
                     Text="{Binding Path=Priority}"/>
          <TextBlock Margin="3,0,3,7"
                     Text="{Binding Path=TaskName}"/>
        </StackPanel>
      </Grid>
    </DataTemplate>
  </ItemsControl.ItemTemplate>
  <!--Use the ItemContainerStyle property to specify the appearance
      of the element that contains the data. This ItemContainerStyle
      gives each item container a margin and a width. There is also
      a trigger that sets a tooltip that shows the description of
      the data object when the mouse hovers over the item container.-->
  <ItemsControl.ItemContainerStyle>
    <Style>
      <Setter Property="Control.Width" Value="100"/>
      <Setter Property="Control.Margin" Value="5"/>
      <Style.Triggers>
        <Trigger Property="Control.IsMouseOver" Value="True">
          <Setter Property="Control.ToolTip"
                  Value="{Binding RelativeSource={x:Static RelativeSource.Self},
                          Path=Content.Description}"/>
        </Trigger>
      </Style.Triggers>
    </Style>
  </ItemsControl.ItemContainerStyle>
</ItemsControl>

다음 스크린 샷은 예제가 렌더링된 모습을 보여 줍니다.

ItemsControl 예제 스크린 샷

ItemTemplate 대신 ItemTemplateSelector를 사용할 수 있습니다. 예제를 보려면 앞 단원을 참조하십시오. 이와 마찬가지로 ItemContainerStyle 대신 ItemContainerStyleSelector를 사용할 수도 있습니다.

ItemsControl의 스타일 관련 속성 중 GroupStyleGroupStyleSelector는 여기에 표시하지 않았습니다.

계층적 데이터 지원

앞에서는 단일 컬렉션에 바인딩하여 컬렉션을 표시하는 방법에 대해서만 살펴보았습니다만, 다른 컬렉션이 포함된 컬렉션을 사용하는 경우도 있습니다. HierarchicalDataTemplate 클래스를 HeaderedItemsControl 형식과 함께 사용하면 이러한 데이터를 표시할 수 있습니다. 다음 예제에서 ListLeagueList는 League 개체의 목록입니다. 각 League 개체에는 Name과 Division 개체 컬렉션이 있습니다. 그리고 각 Division에는 Name과 Team 개체 컬렉션이 있으며, 각 Team 개체에는 Name이 있습니다.

<Window x:Class="SDKSample.Window1"
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  Title="HierarchicalDataTemplate Sample"
  xmlns:src="clr-namespace:SDKSample">
  <DockPanel>
    <DockPanel.Resources>
      <src:ListLeagueList x:Key="MyList"/>

      <HierarchicalDataTemplate DataType    = "{x:Type src:League}"
                                ItemsSource = "{Binding Path=Divisions}">
        <TextBlock Text="{Binding Path=Name}"/>
      </HierarchicalDataTemplate>

      <HierarchicalDataTemplate DataType    = "{x:Type src:Division}"
                                ItemsSource = "{Binding Path=Teams}">
        <TextBlock Text="{Binding Path=Name}"/>
      </HierarchicalDataTemplate>

      <DataTemplate DataType="{x:Type src:Team}">
        <TextBlock Text="{Binding Path=Name}"/>
      </DataTemplate>
    </DockPanel.Resources>

    <Menu Name="menu1" DockPanel.Dock="Top" Margin="10,10,10,10">
        <MenuItem Header="My Soccer Leagues"
                  ItemsSource="{Binding Source={StaticResource MyList}}" />
    </Menu>

    <TreeView>
      <TreeViewItem ItemsSource="{Binding Source={StaticResource MyList}}" Header="My Soccer Leagues" />
    </TreeView>

  </DockPanel>
</Window>

예제에서는 HierarchicalDataTemplate을 사용하면 다른 목록이 포함된 목록 데이터를 쉽게 표시할 수 있음을 보여 줍니다. 다음은 예제의 스크린 샷입니다.

HierarchicalDataTemplate 샘플 스크린 샷

참고 항목

작업

방법: DataTemplate에서 생성된 요소 찾기

개념

성능 최적화: 데이터 바인딩

스타일 지정 및 템플릿

데이터 바인딩 개요

GridView 열 머리글 스타일 및 템플릿 개요