資料範本化概觀

WPF 資料範本化模型對於資料呈現方式的定義,具有相當大的彈性。 WPF 控制項的內建功能支援自訂資料呈現方式。 本主題會先示範如何定義 DataTemplate (英文),之後再介紹其他資料範本化功能,例如以自訂邏輯為基礎的範本選擇,以及階層式資料的顯示支援。

必要條件

本主題著重資料範本化功能,而不是資料繫結概念簡介。 如需基本資料繫結概念的資訊,請參閱資料繫結概觀

DataTemplate (英文) 與資料的呈現方式有關,而且是 WPF 樣式設定和範本化模型提供的眾多功能之一。 如需 WPF 樣式設定和範本化模型 (例如,如何使用 Style (部分機器翻譯) 在控制項上設定屬性) 的簡介,請參閱樣式設定和範本化主題。

此外,請務必了解 Resources,這基本上是讓物件 (例如 Style (部分機器翻譯) 和 DataTemplate (英文)) 可重複使用的要素。 如需詳細資訊,請參閱 XAML 資源

資料範本化基本概念

為了示範 DataTemplate (英文) 之所以重要的原因,我們來研究以下的資料繫結範例。 在這裡範例中,我們有繫結至 Task 物件清單的 ListBox (部分機器翻譯)。 每個 Task 物件各有一個 TaskName (字串)、Description (字串)、Priority (整數),和一個 TaskType型別的屬性,該型別是含有值 HomeWorkEnum

<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 (部分機器翻譯) 目前看起來會像這樣:

顯示 [我的工作清單] ListBox 之 [資料範本化範例簡介] 視窗的螢幕擷取畫面,其中顯示每個來源物件的字串表示 SDKSample.Task。

目前的狀況是若沒有任何具體指示,當 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 (英文)。 若要這麼做,其中一種方法是將 ListBox (部分機器翻譯) 的 ItemTemplate (部分機器翻譯) 屬性設定為 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 (部分機器翻譯) 看起來會像這樣:

顯示 [我的工作清單] ListBox 之 [資料範本化範例簡介] 視窗的螢幕擷取畫面,其中將工作顯示為 TextBlock 元素。

將 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 (英文) 型別的其他控制項上。 如上所示,若為 ItemsControl (部分機器翻譯) 物件 (例如 ListBox (部分機器翻譯)),其為 ItemTemplate (部分機器翻譯) 屬性。 若為 ContentControl (部分機器翻譯) 物件,其為 ContentTemplate (英文) 屬性。

DataType 屬性

DataTemplate (英文) 類別擁有的 DataType (部分機器翻譯) 屬性與 Style (部分機器翻譯) 類別的 TargetType (部分機器翻譯) 屬性非常類似。 因此,您無須照上面的範例為 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 (部分機器翻譯) 上的繫結需要更多的資訊,來分辨您是要繫結到整個集合或要繫結個別物件。 如果您的 ContentControl (部分機器翻譯) 要追蹤 ItemsControl (部分機器翻譯) 類型的選取,您可以將 ContentControl (部分機器翻譯) 繫結的 Path (英文) 屬性設定為「/」,以指出您對目前的項目感興趣。 如需範例,請參閱繫結至集合並根據選取項目顯示資訊。 否則,您必須藉由設定 ContentTemplate (英文) 屬性來明確指定 DataTemplate (英文)。

當您有不同資料物件類型的 CompositeCollection (部分機器翻譯) 時,DataType (部分機器翻譯) 屬性特別有用。 如需範例,請參閱實作 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 (部分機器翻譯) 上將 HorizontalContentAlignment (英文) 設定為 Stretch (英文) 以確保項目的寬度佔滿整個空間:

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

HorizontalContentAlignment (英文) 屬性設定為 Stretch (英文) 時,ListBox (部分機器翻譯) 現在看起來會像這樣:

螢幕擷取畫面:顯示 [我的工作清單] ListBox 已在水平方向上延展為螢幕大小的 [資料範本化範例簡介] 視窗。

使用 DataTriggers 套用屬性值

目前的展示方式並無法分辨出 Task 是家務還是公司的工作。 前面提過,Task 物件有一個型別為 TaskTypeTaskType 屬性,這是具有 HomeWork 這兩個值的列舉。

在下列範例中,如果 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>

現在應用程式看起來就像下面這樣。 家務會用黃色框線框住,而公司工作則有水藍色框線框住:

螢幕擷取畫面:顯示住家和辦公室工作的框線已使用顏色醒目提示之 [我的工作清單] ListBox 的 [資料範本化範例簡介] 視窗。

在此範例中,DataTrigger (英文) 會使用 Setter (部分機器翻譯) 來設定屬性值。 觸發程序類別也有 EnterActions (部分機器翻譯) 和 ExitActions (部分機器翻譯) 屬性可讓您啟動一組動作,例如動畫。 此外,還有一個 MultiDataTrigger (英文) 類別,這可讓您根據多個資料繫結屬性值套用變更。

要達到相同效果,另一個方式是將 BorderBrush (英文) 屬性繫結至 TaskType 屬性,然後使用值轉換器,根據 TaskType 值傳回色彩。 使用轉換器建立上述效果,就效能上來說會快些。 此外,建立自己的轉換器能提供更多的彈性,因為您可以提供自己的邏輯。 最後,要選擇使用哪種方式,取決於個別情況和您的偏好而定。 如需有關如何撰寫轉換器的資訊,請參閱 IValueConverter (部分機器翻譯)。

哪些內容屬於 DataTemplate 的範圍

在上一個範例中,我們使用 DataTemplate.Triggers (英文) 屬性將觸發程序放在 DataTemplate (英文) 內。 觸發程序的 Setter (部分機器翻譯) 會設定 DataTemplate (英文) 內元素 (Border (部分機器翻譯) 元素) 的屬性值。 不過,如果與您的 Setters 有關的屬性不是目前 DataTemplate (英文) 內元素的屬性,則使用適用於 ListBoxItem (部分機器翻譯) 類別的 Style (部分機器翻譯) 來設定屬性可能會更適合 (如果您要繫結的控制項是 ListBox (部分機器翻譯) 的話)。 例如,如果您希望 Trigger (部分機器翻譯) 在滑鼠指向某個項目時以動畫顯示該項目的 Opacity (部分機器翻譯) 值,您可以在 ListBoxItem (部分機器翻譯) 樣式內定義觸發程序。 如需範例,請參閱樣式設定和範本化範例的簡介

一般而言,請記住 DataTemplate (英文) 會套用至每個產生的 ListBoxItem (部分機器翻譯) (如需其實際套用方式和套用位置的詳細資訊,請參閱 ItemTemplate (部分機器翻譯) 頁面)。 DataTemplate (英文) 只與資料物件的展示方式和外觀有關。 在大多數情況下,所有其他展示方面,例如項目在選取之後看起來的樣子,或是 ListBox (部分機器翻譯) 如何配置項目,都不屬於 DataTemplate (英文) 的定義範圍。 如需範例,請參閱 ItemsControl 的樣式設定和範本化一節。

根據資料物件的屬性選擇 DataTemplate

DataType 屬性一節中提到過,您可以為不同的資料物件定義不同的資料範本。 當您有不同型別的 CompositeCollection (部分機器翻譯) 或項目為不同型別的集合時,這就特別有用。 在使用 DataTriggers 套用屬性值一節中,我們說明過,如果集合有相同型別的資料物件時,您可以建立 DataTemplate (英文),然後使用觸發程序,根據每個資料物件的屬性值套用變更。 不過,觸發程序雖然可以讓您套用屬性值或啟動動畫,但無法提供重新建構資料物件結構的彈性。 在某些情況下,您可能需要為相同型別但有不同屬性的資料物件建立不同的 DataTemplate (英文)。

例如,當 Task 物件有一個 Priority 值為 1 時,您可能會想讓它看起來完全不同,以便提醒自己。 在此情況下,您可以建立 DataTemplate (英文) 來顯示高優先順序的 Task 物件。 讓我們將下列 DataTemplate (英文) 新增至 resources 區段:

<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 (英文) 內的元素共用。

若要提供邏輯,以根據資料物件的 Priority 值選擇要使用的 DataTemplate (英文),請建立 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>

若要使用範本選取器資源,請將其指派給 ListBox (部分機器翻譯) 的 ItemTemplateSelector (部分機器翻譯) 屬性。 ListBox (部分機器翻譯) 會針對基礎集合中的每個項目呼叫 TaskListDataTemplateSelectorSelectTemplate (部分機器翻譯) 方法。 該呼叫會將資料物件當做項目參數傳遞。 由該方法傳回的 DataTemplate (英文) 接著會套用到該資料物件。

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

具備範本選取器後,ListBox (部分機器翻譯) 現在會顯示如下:

顯示 [我的工作清單] ListBox 之 [資料範本化範例簡介] 視窗的螢幕擷取畫面,其中以紅色框線醒目顯示 [優先順序 1] 工作。

這個範例的討論到此結束。 如需完整範例,請參閱資料範本化範例簡介

ItemsControl 的樣式設定和範本化

雖然 ItemsControl (部分機器翻譯) 不是使用 DataTemplate (英文) 時唯一可以搭配的控制項類型,但將 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 (部分機器翻譯) 的另外兩個樣式相關屬性為 GroupStyle (部分機器翻譯) 和 GroupStyleSelector (部分機器翻譯)。

支援階層式資料

到目前為止,我們只討論了如何繫結和顯示單一集合。 有時候集合之中可能還有其他集合。 HierarchicalDataTemplate (部分機器翻譯) 類別的設計目的是要與 HeaderedItemsControl (部分機器翻譯) 類型搭配使用以顯示這類資料。 在下列範例中,ListLeagueListLeague 物件的清單。 每個 League 物件都有一個 Name 和一組 Division 物件集合。 每一個 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 範例螢幕擷取畫面

另請參閱