데이터 템플릿 개요

WPF 데이터 템플릿 모델을 사용하면 데이터 표시를 매우 유연하게 정의할 수 있습니다. WPF 컨트롤에는 데이터 표시의 사용자 지정을 지원하는 기본 제공 기능이 있습니다. 이 항목에서는 먼저 DataTemplate를 정의하는 방법을 설명한 다음, 사용자 지정 논리에 따른 템플릿 선택 및 계층적 데이터 표시 지원과 같은 기타 데이터 템플릿 기능을 소개합니다.

사전 요구 사항

이 항목에서는 데이터 템플릿 기능을 집중적으로 살펴보고 데이터 바인딩 개념은 소개하지 않습니다. 기본 데이터 바인딩 개념에 대한 자세한 내용은 데이터 바인딩 개요를 참조하세요.

DataTemplate은 데이터 표시와 관련되고 WPF 스타일 지정 및 템플릿 모델에서 제공되는 많은 기능 중 하나입니다. Style을 사용하여 컨트롤에서 속성을 설정하는 방법과 같은 WPF 스타일 지정 및 템플릿 모델에 대한 간단한 설명은 스타일 지정 및 템플릿 항목을 참조하세요.

또한 기본적으로 StyleDataTemplate과 같이 개체를 재사용 가능하게 하는 Resources를 이해해야 합니다. 리소스에 대한 자세한 내용은 XAML 리소스를 참조하세요.

데이터 템플릿 기본 사항

DataTemplate이 중요한 이유를 설명하기 위해 데이터 바인딩 예제를 살펴보겠습니다. 이 예제에는 Task 개체 목록에 바인딩된 ListBox가 있습니다. 각 Task 개체에는 TaskName(string), Description(string), Priority(int)와 함께 값이 HomeWorkEnum을 나타내는 TaskType 형식 속성이 있습니다.

<Window x:Class="SDKSample.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://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는 현재 다음과 같습니다.

각 소스 개체에 대한 SDKSample.Task 문자열 표현을 표시하는 내 작업 목록 ListBox가 표시된 데이터 템플릿 샘플 소개 창의 스크린샷.

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

예를 들어 Task 클래스가 이 방식으로 ToString 메서드를 재정의하면 nameTaskName 속성에 대한 필드입니다.

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

그러면 ListBox는 다음과 같습니다.

작업 목록을 표시하는 내 작업 목록 ListBox가 표시된 데이터 템플릿 샘플 소개 창의 스크린샷.

하지만 이 방법은 제한적이고 유연하지 않습니다. 또한 XML 데이터에 바인딩할 경우 ToString을 재정의할 수 없습니다.

간단한 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는 다음과 같습니다.

TextBlock 요소로 작업을 표시하는 내 작업 목록 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는 암시적으로 설정됩니다. 따라서 이 DataTemplatex:Key 값을 할당하면 암시적 x:Key가 재정의되고 DataTemplate이 자동으로 적용되지 않습니다.

ContentControlTask 개체 컬렉션에 바인딩하면 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를 보여줍니다.

수정된 DataTemplate과 함께 내 작업 목록 ListBox에 표시된 데이터 템플릿 샘플 소개 창의 스크린샷.

ListBox에서 HorizontalContentAlignmentStretch로 설정하여 항목 너비가 전체 공간을 차지하는지 확인할 수 있습니다.

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

HorizontalContentAlignment 속성을 Stretch로 설정하면 ListBox는 이제 다음과 같이 표시됩니다.

화면 가로에 맞게 늘어난 내 작업 목록 ListBox에 표시된 데이터 템플릿 샘플 소개 창의 스크린샷.

DataTrigger를 사용하여 속성 값 적용

현재 표시로는 Task가 홈 작업 또는 사무실 작업인지 알 수 없습니다. 다시 말하지만, Task 개체에는 값이 HomeWork인 열거형을 나타내는 TaskType 형식의 TaskType 속성이 있습니다.

다음 예제에서 DataTriggerTaskType 속성이 TaskType.Home인 경우 border라는 요소의 BorderBrushYellow로 설정합니다.

<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>

이제 애플리케이션은 다음과 같이 표시됩니다. 홈 작업에는 노란색 테두리가 표시되고 사무실 작업에는 바다색 테두리가 표시됩니다.

집 및 사무실 작업 경계가 색으로 강조 표시된 내 작업 목록 ListBox에 표시된 데이터 템플릿 샘플 소개 창의 스크린샷.

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

같은 효과를 얻을 수 있는 대체 방법은 BorderBrush 속성을 TaskType 속성에 바인딩하고 값 변환기를 사용하여 TaskType 값에 따라 색을 반환하는 것입니다. 변환기를 사용하여 위 효과를 만드는 방법이 성능 면에서 약간 더 효율적입니다. 또한 자체 변환기를 만들면 자체 논리를 제공할 수 있으므로 더 유연하게 작업할 수 있습니다. 결국 선택하는 방법은 시나리오와 기본 설정에 따라 결정됩니다. 변환기를 작성하는 방법에 대한 자세한 내용은 IValueConverter를 참조하세요.

DataTemplate은 무엇으로 구성되나요?

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

일반적으로 DataTemplate은 생성된 각 ListBoxItem에 적용된다는 것에 유의하세요. 실제로 적용되는 방식 및 위치에 대한 자세한 내용은 ItemTemplate 페이지를 참조하세요. DataTemplate은 데이터 개체의 표시 및 모양에만 관련됩니다. 대부분의 경우 항목이 선택될 때 무엇이 표시되는지 또는 ListBox가 항목을 어떻게 배치하는지 등의 표시에 대한 모든 기타 측면은 DataTemplate의 정의에 포함되지 않습니다. 예제를 보려면 ItemsControl 스타일 지정 및 템플릿 만들기 섹션을 참조하세요.

데이터 개체의 속성에 따라 DataTemplate 선택

DataType 속성 섹션에서 다양한 데이터 개체에 대한 서로 다른 데이터 템플릿을 정의할 수 있음을 설명했습니다. 이 기능은 다양한 형식이 포함된 CompositeCollection 또는 다양한 형식의 항목이 포함된 컬렉션이 있을 경우 특히 유용합니다. DataTrigger를 사용하여 속성 값 적용 섹션에서 같은 형식의 데이터 개체로 구성된 컬렉션이 있는 경우 DataTemplate을 만들고 트리거를 사용하여 각 데이터 개체의 속성 값에 따라 변경 내용을 적용할 수 있음을 설명했습니다. 그러나 트리거를 사용하여 속성 값을 적용하거나 애니메이션을 시작할 수 있지만 트리거는 데이터 개체의 구조를 재구성할 수 있는 유연성이 없습니다. 몇몇 시나리오에는 형식이 같지만 속성이 다른 데이터 개체에 대한 서로 다른 DataTemplate을 만들어야 할 수 있습니다.

예를 들어 Task 개체의 Priority 값이 1일 경우 스스로 주의할 수 있도록 완전히 다른 모양을 지정해야 할 수 있습니다. 이 경우 우선 순위가 높은 Task 개체의 표시를 위한 DataTemplate을 만듭니다. 리소스 섹션에 다음 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 속성을 사용합니다. 해당 섹션에 정의된 리소스는 DataTemplate에 있는 요소에서 공유됩니다.

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

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;
        }
    }
}

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

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

<Window.Resources>
<local:TaskListDataTemplateSelector x:Key="myDataTemplateSelector"/>
</Window.Resources>

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

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

템플릿 선택기를 배치하면 이제 ListBox가 다음과 같이 표시됩니다.

빨간색 테두리가 눈에 띄게 표시된 우선순위 1 작업이 있는 내 작업 목록 ListBox에 표시된 데이터 템플릿 샘플 소개 창의 스크린샷.

이것으로 이 예제에 대한 설명을 마칩니다. 전체 샘플을 보려면 Introduction to Data Templating Sample(데이터 템플릿 샘플 소개)을 참조하세요.

ItemsControl 스타일 지정 및 템플릿 만들기

ItemsControlDataTemplate을 사용할 수 있는 유일한 컨트롤 형식이 아니더라도 ItemsControl을 컬렉션에 바인딩하는 것은 매우 일반적인 시나리오입니다. DataTemplate은 무엇으로 구성되나요? 섹션에서는 DataTemplate이 데이터 표시에만 관련된다는 것을 설명했습니다. DataTemplate을 사용하기 적합하지 않은 경우를 파악하려면 ItemsControl에서 제공되는 다양한 스타일 및 템플릿 속성을 이해해야 합니다. 다음 예제는 이러한 각 속성의 기능을 설명하도록 디자인되어 있습니다. 이 예제의 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 형식과 함께 사용하도록 설계되었습니다. 다음 예제에서 ListLeagueListLeague 개체 목록입니다. 각 League 개체에는 NameDivision 개체 컬렉션이 포함됩니다. 각 Division 에는 NameTeam 개체 컬렉션이 포함되고 각 Team 개체에는 Name이 포함됩니다.

<Window x:Class="SDKSample.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://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 샘플 스크린샷

참고 항목