Bagikan melalui


Gambaran Umum Templat Data

Model templat data WPF memberi Anda fleksibilitas yang besar untuk menentukan presentasi data Anda. Kontrol WPF memiliki fungsionalitas bawaan untuk mendukung penyesuaian presentasi data. Topik ini pertama-tama menunjukkan cara menentukan DataTemplate dan kemudian memperkenalkan fitur templat data lainnya, seperti pemilihan templat berdasarkan logika kustom dan dukungan untuk tampilan data hierarkis.

Prasyarat

Topik ini berfokus pada fitur templat data dan bukan pengenalan konsep pengikatan data. Untuk informasi tentang konsep pengikatan data dasar, lihat Gambaran Umum Pengikatan Data .

DataTemplate adalah tentang presentasi data dan merupakan salah satu dari banyak fitur yang disediakan oleh model gaya dan templat WPF. Untuk pengenalan model gaya dan templat WPF, seperti cara menggunakan Style untuk mengatur properti pada kontrol, lihat topik Gaya dan Templating.

Selain itu, penting untuk memahami Resources, yang pada dasarnya apa yang memungkinkan objek seperti Style dan DataTemplate dapat digunakan kembali. Untuk informasi selengkapnya tentang sumber daya, lihat Sumber Daya XAML.

Dasar-Dasar Penggunaan Templat Data

Untuk menunjukkan mengapa DataTemplate penting, mari kita telusuri contoh pengikatan data. Dalam contoh ini, kita memiliki ListBox yang terikat ke daftar objek Task. Setiap objek Task memiliki TaskName (string), Description (string), Priority (int), dan properti jenis TaskType, yang merupakan Enum dengan nilai Home dan Work.

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

Tanpa DataTemplate

Tanpa DataTemplate, ListBox kami saat ini terlihat seperti ini:

Cuplikan layar jendela Pengenalan Sampel Templat Data memperlihatkan Kotak Daftar Tugas Saya yang menampilkan representasi string SDKSample.Task untuk setiap objek sumber.

Apa yang terjadi adalah bahwa tanpa instruksi tertentu, ListBox secara default memanggil ToString saat mencoba menampilkan objek dalam koleksi. Oleh karena itu, jika objek Task mengambil alih metode ToString, maka ListBox menampilkan representasi string dari setiap objek sumber dalam koleksi yang mendasar.

Misalnya, jika kelas Task mengambil alih metode ToString dengan cara ini, di mana name adalah bidang untuk properti TaskName:

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

Kemudian ListBox terlihat seperti berikut ini:

Cuplikan layar jendela Pengenalan Sampel Templat Data memperlihatkan Kotak Daftar Tugas Saya yang menampilkan daftar tugas.

Namun, itu membatasi dan tidak fleksibel. Selain itu, jika Anda mengikat data XML, Anda tidak akan dapat mengambil alih ToString.

Menentukan DataTemplate Sederhana

Solusinya adalah menentukan DataTemplate. Salah satu cara untuk melakukan itu adalah dengan mengatur properti ItemTemplate dari ListBox ke DataTemplate. Apa yang Anda tentukan dalam DataTemplate akan menjadi struktur visual dari objek data. DataTemplate berikut ini cukup sederhana. Kami memberikan instruksi bahwa setiap item muncul sebagai tiga elemen TextBlock dalam StackPanel. Setiap elemen TextBlock terikat ke properti kelas 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>

Data yang mendasar untuk contoh dalam topik ini adalah kumpulan objek CLR. Jika Anda mengikat data XML, konsep dasarnya sama, tetapi ada sedikit perbedaan sinaks. Misalnya, alih-alih memiliki Path=TaskName, Anda akan mengatur XPath ke @TaskName (jika TaskName adalah atribut dari simpul XML Anda).

Sekarang ListBox kami terlihat seperti berikut:

Cuplikan layar jendela Contoh Pengenalan Templat Data yang memperlihatkan ListBox

Membuat DataTemplate sebagai Sumber Daya

Dalam contoh di atas, kami mendefinisikan DataTemplate dalam baris. Lebih umum untuk menentukannya di bagian sumber daya sehingga dapat menjadi objek yang dapat digunakan kembali, seperti dalam contoh berikut:

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

Sekarang Anda dapat menggunakan myTaskTemplate sebagai sumber daya, seperti dalam contoh berikut:

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

Karena myTaskTemplate adalah sumber daya, Anda sekarang dapat menggunakannya pada kontrol lain yang memiliki properti dengan tipe DataTemplate. Seperti yang ditunjukkan di atas, untuk objek ItemsControl, seperti ListBox, ini adalah properti ItemTemplate. Untuk objek ContentControl, ini adalah properti ContentTemplate.

Properti TipeData

Kelas DataTemplate memiliki properti DataType yang sangat mirip dengan properti TargetType kelas Style. Oleh karena itu, alih-alih menentukan x:Key untuk DataTemplate dalam contoh di atas, Anda dapat melakukan hal berikut:

<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 ini diterapkan secara otomatis ke semua objek Task. Perhatikan bahwa dalam hal ini x:Key diatur secara implisit. Oleh karena itu, jika Anda menetapkan nilai DataTemplate ke x:Key, Anda mengesampingkan x:Key yang implisit sehingga DataTemplate tidak akan diterapkan secara otomatis.

Jika Anda mengikat ContentControl ke kumpulan objek Task, ContentControl tidak menggunakan DataTemplate di atas secara otomatis. Ini karena pengikatan pada ContentControl membutuhkan informasi lebih lanjut untuk membedakan apakah Anda ingin mengikat seluruh koleksi atau objek individual. Jika ContentControl Anda melacak pilihan jenis ItemsControl, Anda dapat mengatur properti Path pengikatan ContentControl ke "/" untuk menunjukkan bahwa Anda tertarik dengan item saat ini. Misalnya, lihat Mengikat ke Koleksi dan Menampilkan Informasi Berdasarkan Pilihan. Jika tidak, Anda perlu menentukan DataTemplate secara eksplisit dengan mengatur properti ContentTemplate.

Properti DataType sangat berguna ketika Anda memiliki CompositeCollection berbagai jenis objek data. Misalnya, lihat Menerapkan compositeCollection.

Menambahkan Lainnya ke DataTemplate

Saat ini data muncul dengan informasi yang diperlukan, tetapi pasti ada ruang untuk perbaikan. Mari kita tingkatkan presentasi dengan menambahkan Border, Grid, dan beberapa elemen TextBlock yang menjelaskan data yang sedang ditampilkan.


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

Cuplikan layar berikut menunjukkan ListBox dengan DataTemplateyang dimodifikasi ini:

Cuplikan layar jendela Pengenalan Sampel Templat Data memperlihatkan Kotak Daftar Tugas Saya dengan DataTemplate yang dimodifikasi.

Kita dapat mengatur HorizontalContentAlignment ke Stretch pada ListBox untuk memastikan lebar item mengambil seluruh ruang:

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

Dengan properti HorizontalContentAlignment diatur ke Stretch, ListBox sekarang terlihat seperti ini:

Cuplikan layar jendela Pengenalan Sampel Templat Data memperlihatkan Kotak Daftar Tugas Saya yang direntangkan agar pas dengan layar secara horizontal.

Menggunakan DataTriggers untuk Menerapkan Nilai Properti

Presentasi saat ini tidak memberi tahu kami apakah Task adalah tugas rumah atau tugas kantor. Ingatlah bahwa objek Task memiliki properti jenis TaskTypeTaskType , yang merupakan enumerasi dengan nilai Home dan Work.

Dalam contoh berikut, DataTrigger menyetel BorderBrush dari elemen bernama border ke Yellow bila properti TaskType adalah TaskType.Home.

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

Aplikasi kami sekarang terlihat seperti berikut ini. Tugas rumah muncul dengan bingkai kuning dan tugas kantor muncul dengan bingkai biru laut.

Cuplikan layar jendela Sampel Pengenalan Templat Data memperlihatkan ListBox Daftar Tugas Saya dengan batas tugas rumah dan kantor disorot dalam warna.

Dalam contoh ini, DataTrigger menggunakan Setter untuk mengatur nilai properti. Kelas pemicu juga memiliki properti EnterActions dan ExitActions yang memungkinkan Anda memulai serangkaian tindakan seperti animasi. Selain itu, ada juga kelas MultiDataTrigger yang memungkinkan Anda menerapkan perubahan berdasarkan beberapa nilai properti terikat data.

Cara alternatif untuk mencapai efek yang sama adalah dengan mengikat properti BorderBrush ke properti TaskType dan menggunakan pengonversi nilai untuk mengembalikan warna berdasarkan nilai TaskType. Membuat efek di atas menggunakan pengonversi sedikit lebih efisien dalam hal performa. Selain itu, membuat konverter Anda sendiri memberi Anda lebih banyak fleksibilitas karena Anda menyediakan logika Anda sendiri. Pada akhirnya, teknik mana yang Anda pilih tergantung pada skenario dan preferensi Anda. Untuk informasi tentang cara menulis pengonversi, lihat IValueConverter.

Apa yang Termasuk dalam DataTemplate?

Dalam contoh sebelumnya, kami menempatkan pemicu dalam DataTemplate menggunakan properti DataTemplate.Triggers. Pemicu Setter menetapkan nilai dari sebuah properti elemen (elemen Border) yang berada di dalam DataTemplate. Namun, jika properti yang menjadi perhatian Setters Anda bukan merupakan properti dari elemen yang berada dalam DataTemplatesaat ini, mungkin lebih cocok untuk mengatur properti dengan menggunakan Style yang merupakan bagian dari kelas ListBoxItem (jika kontrol yang diikat adalah ListBox). Misalnya, jika Anda ingin Trigger menganimasikan nilai Opacity item saat mouse menunjuk ke item, Anda menentukan pemicu dalam gaya ListBoxItem. Misalnya, lihat Pengenalan contoh styling dan templating.

Secara umum, perlu diingat bahwa DataTemplate diterapkan pada masing-masing ListBoxItem yang dihasilkan. Untuk informasi selengkapnya tentang bagaimana dan di mana hal itu sebenarnya diterapkan, lihat halaman ItemTemplate. DataTemplate Anda hanya berfokus pada presentasi dan penampilan objek data. Dalam kebanyakan kasus, semua aspek presentasi lainnya, seperti seperti apa item saat dipilih atau bagaimana ListBox menata item, tidak termasuk dalam definisi DataTemplate. Misalnya, lihat bagian Gaya dan Templat ItemsControl.

Memilih DataTemplate Berdasarkan Properti Objek Data

Di bagian properti DataType, kami membahas bahwa Anda dapat menentukan templat data yang berbeda untuk objek data yang berbeda. Itu sangat berguna ketika Anda memiliki CompositeCollection dari berbagai jenis atau koleksi dengan item-item dari jenis yang berbeda. Di bagian Gunakan DataTriggers untuk Menerapkan Nilai Properti, kami telah menunjukkan bahwa jika Anda memiliki kumpulan jenis objek data yang sama, Anda dapat membuat DataTemplate lalu menggunakan pemicu untuk menerapkan perubahan berdasarkan nilai properti setiap objek data. Namun, pemicu memungkinkan Anda menerapkan nilai properti atau memulai animasi tetapi tidak memberi Anda fleksibilitas untuk membangun kembali struktur objek data Anda. Beberapa skenario mungkin mengharuskan Anda membuat DataTemplate yang berbeda untuk objek data dengan jenis yang sama tetapi memiliki properti yang berbeda.

Misalnya, ketika objek Task memiliki nilai Priority1, Anda mungkin ingin memberikan tampilan yang sama sekali berbeda untuk berfungsi sebagai pemberitahuan untuk diri Anda sendiri. Dalam hal ini, Anda membuat DataTemplate untuk tampilan objek Task berprioritas tinggi. Mari kita tambahkan DataTemplate berikut ke bagian sumber daya:

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

Contoh ini menggunakan properti DataTemplate.Resources. Sumber daya yang ditentukan di bagian tersebut dibagikan oleh elemen dalam DataTemplate.

Untuk menyediakan logika untuk memilih DataTemplate mana yang akan digunakan berdasarkan nilai Priority objek data, buat subkelas DataTemplateSelector dan ambil alih metode SelectTemplate. Dalam contoh berikut, metode SelectTemplate menyediakan logika untuk mengembalikan templat yang sesuai berdasarkan nilai properti Priority. Templat yang akan dikembalikan ditemukan dalam sumber daya elemen Window yang menyelimuti.

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

Kita kemudian dapat mendeklarasikan TaskListDataTemplateSelector sebagai sumber daya:

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

Untuk menggunakan sumber daya selektor template, tetapkan pada properti ItemTemplateSelector dari ListBox. ListBox memanggil metode SelectTemplate dari TaskListDataTemplateSelector untuk setiap item dalam koleksi dasar. Panggilan meneruskan objek data sebagai parameter item. DataTemplate yang dikembalikan oleh metode kemudian diterapkan ke objek data tersebut.

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

Dengan pemilih template sudah terpasang, ListBox sekarang muncul sebagai berikut:

Cuplikan layar jendela Pengenalan Sampel Templat Data memperlihatkan Kotak Daftar Tugas Saya dengan tugas Prioritas 1 yang ditampilkan dengan batas merah.

Ini menyimpulkan diskusi kami tentang contoh ini. Untuk sampel lengkapnya, lihat Pengenalan Sampel Templat Data.

Menata dan Membuat Templat ItemControl

Meskipun ItemsControl bukan satu-satunya jenis kontrol yang dapat Anda gunakan dengan DataTemplate, ini adalah skenario yang sangat umum untuk menghubungkan ItemsControl dengan sebuah koleksi. Di bagian Apa yang Termasuk dalam DataTemplate, kami membahas bahwa definisi DataTemplate Anda seharusnya hanya berkaitan dengan presentasi data. Untuk mengetahui kapan tidak cocok untuk menggunakan DataTemplate penting untuk memahami berbagai gaya dan properti templat yang disediakan oleh ItemsControl. Contoh berikut dirancang untuk mengilustrasikan fungsi masing-masing properti ini. ItemsControl dalam contoh ini terikat ke koleksi Tasks yang sama seperti pada contoh sebelumnya. Untuk tujuan demonstrasi, gaya dan templat dalam contoh ini semuanya dinyatakan sebaris.

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

Berikut ini adalah cuplikan layar contoh saat dirender:

cuplikan layar contoh ItemsControl

Perhatikan bahwa alih-alih menggunakan ItemTemplate, Anda dapat menggunakan ItemTemplateSelector. Lihat bagian sebelumnya untuk contoh. Demikian pula, alih-alih menggunakan ItemContainerStyle, Anda memiliki opsi untuk menggunakan ItemContainerStyleSelector.

Dua properti terkait gaya lainnya dari ItemsControl yang tidak ditampilkan di sini adalah GroupStyle dan GroupStyleSelector.

Dukungan untuk Data Hierarkis

Sejauh ini kami hanya melihat cara melakukan pengikatan dengan dan menampilkan satu koleksi data. Terkadang Anda memiliki koleksi yang berisi koleksi lain. Kelas HierarchicalDataTemplate dirancang untuk digunakan dengan jenis HeaderedItemsControl untuk menampilkan data tersebut. Dalam contoh berikut, ListLeagueList adalah daftar objek League. Setiap objek League memiliki Name dan kumpulan objek Division. Setiap Division memiliki Name dan kumpulan objek Team, dan setiap objek Team memiliki 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>

Contoh menunjukkan bahwa dengan penggunaan HierarchicalDataTemplate, Anda dapat dengan mudah menampilkan data daftar yang berisi daftar lain. Berikut ini adalah cuplikan layar contoh.

cuplikan layar sampel HierarchicalDataTemplate

Lihat juga