資料範本化概觀Data Templating Overview

WPF 資料範本化模型對於資料呈現方式的定義,具有相當大的彈性。The WPF data templating model provides you with great flexibility to define the presentation of your data. WPF 控制項的內建功能支援自訂資料呈現方式。WPF controls have built-in functionality to support the customization of data presentation. 本主題首先會示範如何定義 DataTemplate,然後引進其他資料範本化功能,例如以自訂邏輯為基礎的範本選擇,以及顯示階層式資料的支援。This topic first demonstrates how to define a DataTemplate and then introduces other data templating features, such as the selection of templates based on custom logic and the support for the display of hierarchical data.

PrerequisitesPrerequisites

本主題著重資料範本化功能,而不是資料繫結概念簡介。This topic focuses on data templating features and is not an introduction of data binding concepts. 如需基本資料繫結概念的資訊,請參閱資料繫結概觀For information about basic data binding concepts, see the Data Binding Overview.

DataTemplate 是關於資料的呈現方式,而且是 WPF 樣式和範本化模型提供的眾多功能之一。DataTemplate is about the presentation of data and is one of the many features provided by the WPF styling and templating model. 如需 WPF 樣式和範本化模型的簡介,例如如何使用 Style 設定控制項的屬性,請參閱樣式設定和範本化主題。For an introduction of the WPF styling and templating model, such as how to use a Style to set properties on controls, see the Styling and Templating topic.

此外,請務必瞭解 Resources,這基本上是讓 StyleDataTemplate 等物件可重複使用的方式。In addition, it is important to understand Resources, which are essentially what enable objects such as Style and DataTemplate to be reusable. 如需詳細資訊,請參閱 XAML 資源For more information on resources, see XAML Resources.

資料範本化基本概念Data Templating Basics

為了示範 DataTemplate 的重要性,讓我們逐步解說資料系結範例。To demonstrate why DataTemplate is important, let's walk through a data binding example. 在此範例中,我們有一個系結至 Task 物件清單的 ListBoxIn this example, we have a ListBox that is bound to a list of Task objects. 每個 Task 物件各有一個 TaskName (字串)、Description (字串)、Priority (整數),和一個 TaskType型別的屬性,該型別是含有值 HomeWorkEnumEach Task object has a TaskName (string), a Description (string), a Priority (int), and a property of type TaskType, which is an Enum with values Home and 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>

沒有 DataTemplateWithout a DataTemplate

如果沒有 DataTemplate,我們的 ListBox 目前如下所示:Without a DataTemplate, our ListBox currently looks like this:

資料範本化範例螢幕擷取畫面Data templating sample screenshot

發生的情況是,沒有任何特定的指示,ListBox 在嘗試顯示集合中的物件時,預設會呼叫 ToStringWhat's happening is that without any specific instructions, the ListBox by default calls ToString when trying to display the objects in the collection. 因此,如果 Task 物件會覆寫 ToString 方法,則 ListBox 會顯示基礎集合中每個來源物件的字串表示。Therefore, if the Task object overrides the ToString method, then the ListBox displays the string representation of each source object in the underlying collection.

例如,如果 Task 類別以此方式覆寫 ToString 方法,而其中 nameTaskName屬性的欄位︰For example, if the Task class overrides the ToString method this way, where name is the field for the TaskName property:

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

然後,ListBox 看起來如下所示:Then the ListBox looks like the following:

資料範本化範例螢幕擷取畫面Data templating sample screenshot

不過,這是有限制的,而且缺乏彈性。However, that is limiting and inflexible. 此外,如果您要系結至 XML 資料,就無法覆寫 ToStringAlso, if you are binding to XML data, you wouldn't be able to override ToString.

定義簡單的 DataTemplateDefining a Simple DataTemplate

解決方法是定義 DataTemplateThe solution is to define a DataTemplate. 其中一種方法是將 ListBoxItemTemplate 屬性設定為 DataTemplateOne way to do that is to set the ItemTemplate property of the ListBox to a DataTemplate. 您在 DataTemplate 中指定的內容會成為資料物件的視覺化結構。What you specify in your DataTemplate becomes the visual structure of your data object. 下列 DataTemplate 相當簡單。The following DataTemplate is fairly simple. 我們會提供每個專案在 StackPanel中顯示為三個 TextBlock 元素的指示。We are giving instructions that each item appears as three TextBlock elements within a StackPanel. 每個 TextBlock 元素都會系結至 Task 類別的屬性。Each TextBlock element is bound to a property of the Task class.

<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 物件的集合。The underlying data for the examples in this topic is a collection of CLR objects. 如果您要系結至 XML 資料,基本概念是相同的,但有些微的語法差異。If you are binding to XML data, the fundamental concepts are the same, but there is a slight syntactic difference. 例如,您可以將 XPath 設定為 @TaskName (如果 TaskName 是 XML 節點的屬性),而不是擁有 Path=TaskNameFor example, instead of having Path=TaskName, you would set XPath to @TaskName (if TaskName is an attribute of your XML node).

現在,我們的 ListBox 看起來如下所示:Now our ListBox looks like the following:

資料範本化範例螢幕擷取畫面Data templating sample screenshot

將 DataTemplate 建立為資源Creating the DataTemplate as a Resource

在上述範例中,我們定義了內嵌 DataTemplateIn the above example, we defined the DataTemplate inline. 更常見的是將它定義於資源區段中以成為可重複使用的物件,如下列範例所述:It is more common to define it in the resources section so it can be a reusable object, as in the following example:

<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 做為資源,如下列範例所示︰Now you can use myTaskTemplate as a resource, as in the following example:

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

因為 myTaskTemplate 是資源,所以您現在可以在具有 DataTemplate 類型之屬性的其他控制項上使用它。Because myTaskTemplate is a resource, you can now use it on other controls that have a property that takes a DataTemplate type. 如上所示,針對 ItemsControl 物件(例如 ListBox),它是 ItemTemplate 屬性。As shown above, for ItemsControl objects, such as the ListBox, it is the ItemTemplate property. 若為 ContentControl 物件,則為 ContentTemplate 屬性。For ContentControl objects, it is the ContentTemplate property.

DataType 屬性The DataType Property

DataTemplate 類別具有 DataType 屬性,與 Style 類別的 TargetType 屬性非常類似。The DataTemplate class has a DataType property that is very similar to the TargetType property of the Style class. 因此,您可以執行下列動作,而不是在上述範例中指定 DataTemplatex:KeyTherefore, instead of specifying an x:Key for the DataTemplate in the above example, you can do the following:

<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 物件。This DataTemplate gets applied automatically to all Task objects. 請注意,在此情況下,x:Key 是隱含設定的。Note that in this case the x:Key is set implicitly. 因此,如果您將此 DataTemplate x:Key 值,就會覆寫隱含的 x:Key 而且不會自動套用 DataTemplateTherefore, if you assign this DataTemplate an x:Key value, you are overriding the implicit x:Key and the DataTemplate would not be applied automatically.

如果您要將 ContentControl 系結至 Task 物件的集合,ContentControl 不會自動使用上述 DataTemplateIf you are binding a ContentControl to a collection of Task objects, the ContentControl does not use the above DataTemplate automatically. 這是因為 ContentControl 上的系結需要詳細資訊,以區別您要系結至整個集合或個別物件。This is because the binding on a ContentControl needs more information to distinguish whether you want to bind to an entire collection or the individual objects. 如果您的 ContentControl 追蹤 ItemsControl 類型的選擇,您可以將 ContentControl 系結的 Path 屬性設定為 "/",表示您對目前的專案感興趣。If your ContentControl is tracking the selection of an ItemsControl type, you can set the Path property of the ContentControl binding to "/" to indicate that you are interested in the current item. 如需範例,請參閱繫結至集合並根據選取項目顯示資訊For an example, see Bind to a Collection and Display Information Based on Selection. 否則,您必須藉由設定 ContentTemplate 屬性,明確地指定 DataTemplateOtherwise, you need to specify the DataTemplate explicitly by setting the ContentTemplate property.

當您有不同類型之資料物件的 CompositeCollection 時,DataType 屬性特別有用。The DataType property is particularly useful when you have a CompositeCollection of different types of data objects. 如需範例,請參閱實作 CompositeCollectionFor an example, see Implement a CompositeCollection.

加入更多內容至 DataTemplateAdding More to the DataTemplate

目前資料是以所需的資訊出現,不過還有很大的改進空間。Currently the data appears with the necessary information, but there's definitely room for improvement. 讓我們藉由新增 BorderGrid和一些描述所顯示資料的 TextBlock 元素,來改善簡報。Let's improve on the presentation by adding a Border, a Grid, and some TextBlock elements that describe the data that is being displayed.


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

下列螢幕擷取畫面顯示此已修改 DataTemplateListBoxThe following screenshot shows the ListBox with this modified DataTemplate:

資料範本化範例螢幕擷取畫面Data templating sample screenshot

我們可以將 HorizontalContentAlignment 設定為 ListBox 上的 Stretch,以確保專案的寬度佔用整個空間:We can set HorizontalContentAlignment to Stretch on the ListBox to make sure the width of the items takes up the entire space:

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

HorizontalContentAlignment 屬性設定為 [Stretch] 時,ListBox 現在如下所示:With the HorizontalContentAlignment property set to Stretch, the ListBox now looks like this:

資料範本化範例螢幕擷取畫面Data templating sample screenshot

使用 DataTriggers 套用屬性值Use DataTriggers to Apply Property Values

目前的展示方式並無法分辨出 Task 是家務還是公司的工作。The current presentation does not tell us whether a Task is a home task or an office task. 前面提過,Task 物件有一個型別為 TaskTypeTaskType 屬性,這是具有 HomeWork 這兩個值的列舉。Remember that the Task object has a TaskType property of type TaskType, which is an enumeration with values Home and Work.

在下列範例中,DataTrigger 會將名為 border 的元素 BorderBrush 設定為 Yellow 如果 TaskType 屬性為 TaskType.HomeIn the following example, the DataTrigger sets the BorderBrush of the element named border to Yellow if the TaskType property is 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>

現在應用程式看起來就像下面這樣。Our application now looks like the following. 家務會用黃色框線框住,而公司工作則有水藍色框線框住:Home tasks appear with a yellow border and office tasks appear with an aqua border:

資料範本化範例螢幕擷取畫面Data templating sample screenshot

在此範例中,DataTrigger 會使用 Setter 來設定屬性值。In this example the DataTrigger uses a Setter to set a property value. 觸發程式類別也具有 EnterActionsExitActions 屬性,可讓您啟動一組動作,例如動畫。The trigger classes also have the EnterActions and ExitActions properties that allow you to start a set of actions such as animations. 此外,還有一個 MultiDataTrigger 類別,可讓您根據多個資料系結屬性值來套用變更。In addition, there is also a MultiDataTrigger class that allows you to apply changes based on multiple data-bound property values.

另一種達成相同效果的方法,就是將 BorderBrush 屬性系結至 TaskType 屬性,並使用值轉換器根據 TaskType 值傳回色彩。An alternative way to achieve the same effect is to bind the BorderBrush property to the TaskType property and use a value converter to return the color based on the TaskType value. 使用轉換器建立上述效果,就效能上來說會快些。Creating the above effect using a converter is slightly more efficient in terms of performance. 此外,建立自己的轉換器能提供更多的彈性,因為您可以提供自己的邏輯。Additionally, creating your own converter gives you more flexibility because you are supplying your own logic. 最後,要選擇使用哪種方式,取決於個別情況和您的偏好而定。Ultimately, which technique you choose depends on your scenario and your preference. 如需如何撰寫轉換器的詳細資訊,請參閱 IValueConverterFor information about how to write a converter, see IValueConverter.

哪些內容屬於 DataTemplate 的範圍What Belongs in a DataTemplate?

在上述範例中,我們使用 DataTemplate將觸發程式放在 DataTemplate 中。TriggersIn the previous example, we placed the trigger within the DataTemplate using the DataTemplate.Triggers 屬性。property. 觸發程式的 Setter 會設定 DataTemplate內元素(Border 元素)的屬性值。The Setter of the trigger sets the value of a property of an element (the Border element) that is within the DataTemplate. 不過,如果您 Setters 關心的屬性不是目前 DataTemplate內專案的屬性,則使用 ListBoxItem 類別的 Style 來設定屬性可能比較適合(如果您要系結的控制項是ListBox)。However, if the properties that your Setters are concerned with are not properties of elements that are within the current DataTemplate, it may be more suitable to set the properties using a Style that is for the ListBoxItem class (if the control you are binding is a ListBox). 例如,如果您想要 Trigger 在滑鼠指向專案時以動畫顯示專案的 Opacity 值,您可以在 ListBoxItem 樣式中定義觸發程式。For example, if you want your Trigger to animate the Opacity value of the item when a mouse points to an item, you define triggers within a ListBoxItem style. 如需範例,請參閱樣式設定和範本化範例的簡介For an example, see the Introduction to Styling and Templating Sample.

一般來說,請記住,DataTemplate 會套用至每個產生的 ListBoxItem (如需實際套用方式和位置的詳細資訊,請參閱 ItemTemplate 頁面)。In general, keep in mind that the DataTemplate is being applied to each of the generated ListBoxItem (for more information about how and where it is actually applied, see the ItemTemplate page.). 您的 DataTemplate 只關心資料物件的呈現和外觀。Your DataTemplate is concerned with only the presentation and appearance of the data objects. 在大部分情況下,簡報的所有其他層面(例如選取專案時的外觀,或 ListBox 設定項目的方式)都不屬於 DataTemplate的定義。In most cases, all other aspects of presentation, such as what an item looks like when it is selected or how the ListBox lays out the items, do not belong in the definition of a DataTemplate. 如需範例,請參閱 ItemsControl 的樣式設定和範本化一節。For an example, see the Styling and Templating an ItemsControl section.

根據資料物件的屬性選擇 DataTemplateChoosing a DataTemplate Based on Properties of the Data Object

DataType 屬性一節中提到過,您可以為不同的資料物件定義不同的資料範本。In The DataType Property section, we discussed that you can define different data templates for different data objects. 當您有不同類型的 CompositeCollection 或具有不同類型之專案的集合時,這會特別有用。That is especially useful when you have a CompositeCollection of different types or collections with items of different types. 在 [使用 datatrigger 來套用屬性值] 區段中,我們顯示如果您有相同類型之資料物件的集合,您可以建立 DataTemplate 然後使用觸發程式,根據每個資料物件的屬性值來套用變更。In the Use DataTriggers to Apply Property Values section, we have shown that if you have a collection of the same type of data objects you can create a DataTemplate and then use triggers to apply changes based on the property values of each data object. 不過,觸發程序雖然可以讓您套用屬性值或啟動動畫,但無法提供重新建構資料物件結構的彈性。However, triggers allow you to apply property values or start animations but they don't give you the flexibility to reconstruct the structure of your data objects. 在某些情況下,您可能需要針對屬於相同類型但具有不同屬性的資料物件,建立不同的 DataTemplateSome scenarios may require you to create a different DataTemplate for data objects that are of the same type but have different properties.

例如,當 Task 物件有一個 Priority 值為 1 時,您可能會想讓它看起來完全不同,以便提醒自己。For example, when a Task object has a Priority value of 1, you may want to give it a completely different look to serve as an alert for yourself. 在此情況下,您會建立顯示高優先順序 Task 物件的 DataTemplateIn that case, you create a DataTemplate for the display of the high-priority Task objects. 讓我們將下列 DataTemplate 新增至 resources 區段:Let's add the following DataTemplate to the resources section:

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

請注意,此範例使用 DataTemplateResourcesNotice this example uses the DataTemplate.Resources 屬性。property. 該區段中定義的資源會由 DataTemplate內的元素共用。Resources defined in that section are shared by the elements within the DataTemplate.

若要提供邏輯以根據資料物件的 Priority 值來選擇要使用哪一個 DataTemplate,請建立 DataTemplateSelector 的子類別,並覆寫 SelectTemplate 方法。To supply logic to choose which DataTemplate to use based on the Priority value of the data object, create a subclass of DataTemplateSelector and override the SelectTemplate method. 在下列範例中,SelectTemplate 方法會根據 Priority 屬性的值,提供傳回適當範本的邏輯。In the following example, the SelectTemplate method provides logic to return the appropriate template based on the value of the Priority property. 在包裹 Window 元素的資源中,可以找到要傳回的範本。The template to return is found in the resources of the enveloping Window element.

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 為資源:We can then declare the TaskListDataTemplateSelector as a resource:

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

若要使用範本選取器資源,請將它指派給 ListBoxItemTemplateSelector 屬性。To use the template selector resource, assign it to the ItemTemplateSelector property of the ListBox. ListBox 會針對基礎集合中的每個專案,呼叫 TaskListDataTemplateSelectorSelectTemplate 方法。The ListBox calls the SelectTemplate method of the TaskListDataTemplateSelector for each of the items in the underlying collection. 該呼叫會將資料物件當做項目參數傳遞。The call passes the data object as the item parameter. 然後,方法所傳回的 DataTemplate 會套用至該資料物件。The DataTemplate that is returned by the method is then applied to that data object.

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

範本選取器備妥之後,ListBox 現在會如下所示:With the template selector in place, the ListBox now appears as follows:

資料範本化範例螢幕擷取畫面Data templating sample screenshot

這個範例的討論到此結束。This concludes our discussion of this example. 如需完整範例,請參閱資料範本化範例簡介For the complete sample, see Introduction to Data Templating Sample.

ItemsControl 的樣式設定和範本化Styling and Templating an ItemsControl

雖然 ItemsControl 不是您可以搭配使用 DataTemplate 的唯一控制項類型,但它是將 ItemsControl 系結至集合的一個很常見的案例。Even though the ItemsControl is not the only control type that you can use a DataTemplate with, it is a very common scenario to bind an ItemsControl to a collection. DataTemplate一節中,我們討論了 DataTemplate 的定義應該只關心資料的呈現。In the What Belongs in a DataTemplate section we discussed that the definition of your DataTemplate should only be concerned with the presentation of data. 為了知道不適合使用 DataTemplate,請務必瞭解 ItemsControl所提供的不同樣式和範本屬性。In order to know when it is not suitable to use a DataTemplate it is important to understand the different style and template properties provided by the ItemsControl. 下列範例是設計來說明每個屬性的功能。The following example is designed to illustrate the function of each of these properties. 此範例中的 ItemsControl 系結至與上一個範例相同的 Tasks 集合。The ItemsControl in this example is bound to the same Tasks collection as in the previous example. 為方便示範,這個範例中的樣式和範本都是內嵌宣告的。For demonstration purposes, the styles and templates in this example are all declared inline.

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

下圖是範例呈現的畫面:The following is a screenshot of the example when it is rendered:

ItemsControl 範例螢幕擷取畫面ItemsControl example screenshot

請注意,您可以使用 ItemTemplateSelector,而不是使用 ItemTemplateNote that instead of using the ItemTemplate, you can use the ItemTemplateSelector. 請參閱上一節中的範例。Refer to the previous section for an example. 同樣地,您可以選擇使用 ItemContainerStyleSelector,而不是使用 ItemContainerStyleSimilarly, instead of using the ItemContainerStyle, you have the option to use the ItemContainerStyleSelector.

此處未顯示之 ItemsControl 的兩個其他樣式相關屬性會 GroupStyleGroupStyleSelectorTwo other style-related properties of the ItemsControl that are not shown here are GroupStyle and GroupStyleSelector.

支援階層式資料Support for Hierarchical Data

到目前為止,我們只討論了如何繫結和顯示單一集合。So far we have only looked at how to bind to and display a single collection. 有時候集合之中可能還有其他集合。Sometimes you have a collection that contains other collections. HierarchicalDataTemplate 類別是設計用來搭配 HeaderedItemsControl 類型來顯示這類資料。The HierarchicalDataTemplate class is designed to be used with HeaderedItemsControl types to display such data. 在下列範例中,ListLeagueListLeague 物件的清單。In the following example, ListLeagueList is a list of League objects. 每個 League 物件都有一個 Name 和一組 Division 物件集合。Each League object has a Name and a collection of Division objects. 每一個 Division 都有一個 NameTeam 物件的集合,並且每一個 Team 物件都有一個 NameEach Division has a Name and a collection of Team objects, and each Team object has a 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,您可以輕鬆地顯示包含其他清單的清單資料。The example shows that with the use of HierarchicalDataTemplate, you can easily display list data that contains other lists. 以下是範例的螢幕擷取畫面。The following is a screenshot of the example.

HierarchicalDataTemplate 範例螢幕擷取畫面HierarchicalDataTemplate sample screenshot

請參閱See also