Übersicht über Datenvorlagen

Mithilfe des WPF-Datenvorlagenmodells können Sie die Darstellung Ihrer Daten flexibel definieren. WPF-Steuerelemente verfügen über integrierte Funktionen, die die Anpassung der Datendarstellung unterstützen. In diesem Thema wird zunächst die Definition einer DataTemplate demonstriert, und anschließend werden weitere Datenvorlagenfeatures vorgestellt, wie z. B. die Auswahl von Vorlagen anhand benutzerdefinierter Logik und die Unterstützung der Anzeige hierarchischer Daten.

Dieses Thema enthält folgende Abschnitte.

  • Vorbereitungsmaßnahmen
  • Grundlagen zu Datenvorlagen
  • Hinzufügen weiterer Elemente zur DataTemplate
  • Auswählen einer DataTemplate anhand von Eigenschaften des Datenobjekts
  • Formatierung und Vorlagen für ItemsControl
  • Unterstützung hierarchischer Daten
  • Verwandte Abschnitte

Vorbereitungsmaßnahmen

Der Schwerpunkt dieses Themas liegt auf Datenvorlagenfeatures. Es stellt keine Einführung in Datenbindungsbegriffe dar. Informationen über grundlegende Datenbindungskonzepte finden Sie unter Übersicht über Datenbindung.

DataTemplate bezieht sich auf die Darstellung von Daten und gehört zu den zahlreichen Features des Formatierungs- und Vorlagenmodells von WPF. Eine Einführung in das Formatierungs- und Vorlagenmodell von WPF, z. B. in die Verwendung von Style zur Festlegung von Eigenschaften bei Steuerelementen, finden Sie im Thema Erstellen von Formaten und Vorlagen.

Darüber hinaus sollten Sie sich mit Resources vertraut machen, womit im Wesentlichen die Wiederverwendbarkeit von Objekten wie Style und DataTemplate ermöglicht wird. Weitere Informationen zu Ressourcen finden Sie unter Übersicht über Ressourcen.

Grundlagen zu Datenvorlagen

Dieser Abschnitt enthält folgende Unterabschnitte.

  • Ohne DataTemplate
  • Definieren einer einfachen DataTemplate
  • Erstellen der DataTemplate als Ressource
  • Die DataType-Eigenschaft

Die Bedeutung von DataTemplate soll anhand eines Datenbindungsbeispiels veranschaulicht werden. In diesem Beispiel liegt eine ListBox vor, die an eine Liste von Task-Objekten gebunden ist. Jedes Task-Objekt verfügt über TaskName (string), Description (string), Priority (int) und eine Eigenschaft des TaskType-Typs, wobei es sich um ein Enum mit dem Home-Wert und dem Work-Wert handelt.

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

Ohne DataTemplate

Ohne DataTemplate sieht die ListBox folgendermaßen aus:

Bildschirmabbildung für Datenvorlagen-Beispiel

Ohne bestimmte Anweisungen wird durch ListBox standardmäßig ToString aufgerufen, wenn versucht wird, die Objekte in der Auflistung anzuzeigen. Wenn das Task-Objekt die ToString-Methode überschreibt, zeigt ListBox deshalb eine Zeichenfolgendarstellung der einzelnen Quellobjekte in der zugrunde liegenden Auflistung an.

Wenn z. B. die Task-Klasse auf diese Weise die ToString-Methode überschreibt, wobei name das Feld für die TaskName-Eigenschaft darstellt:

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

Dann sieht ListBox folgendermaßen aus:

Bildschirmabbildung für Datenvorlagen-Beispiel

Das ist jedoch einschränkend und unflexibel. Zudem können Sie beim Binden an XML-Daten den ToString-Wert nicht überschreiben.

Definieren einer einfachen DataTemplate

Die Lösung besteht in der Definition einer DataTemplate. Dies kann durch Festlegen der ItemTemplate-Eigenschaft von ListBox auf DataTemplate geschehen. Die Angaben in der DataTemplate bilden die visuelle Struktur des Datenobjekts. Die folgende DataTemplate ist recht einfach. Wir geben Anweisungen, dass jedes Element als drei TextBlock-Elemente in einem StackPanel angezeigt wird. Jedes TextBlock-Element wird an eine Eigenschaft der Task-Klasse gebunden.

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

Bei den zugrunde liegenden Daten für die Beispiele in diesem Thema handelt es sich um eine Auflistung von CLR-Objekten. Wenn Sie eine Bindung an XML-Daten vornehmen, stimmen die grundsätzlichen Konzepte überein, es besteht jedoch ein kleiner syntaktischer Unterschied. Statt Path=TaskName würden Sie z. B. XPath auf @TaskName festlegen (wenn TaskName ein Attribut des XML-Knotens ist).

Jetzt sieht die ListBox aus unserem Beispiel wie folgt aus:

Bildschirmabbildung für Datenvorlagen-Beispiel

Erstellen der DataTemplate als Ressource

Im Beispiel oben wurde DataTemplate inline definiert. Es ist jedoch üblicher, dies im Ressourcenabschnitt zu definieren, damit es wiederverwendet werden kann, wie im folgenden Beispiel veranschaulicht:

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

Sie können myTaskTemplate nun als Ressource verwenden, wie im folgenden Beispiel veranschaulicht:

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

Da myTaskTemplate eine Ressource ist, können Sie es nun auf anderen Steuerelementen verwenden, die über eine Eigenschaft verfügen, die einen DataTemplate-Typ annimmt. Wie oben gezeigt, stellt es bei ItemsControl-Objekten, wie z. B. ListBox, die ItemTemplate-Eigenschaft dar. Bei ContentControl-Objekten ist es die ContentTemplate-Eigenschaft.

Die DataType-Eigenschaft

Die DataTemplate-Klasse hat eine DataType-Eigenschaft, die der TargetType-Eigenschaft der Style-Klasse sehr ähnlich ist. Anstatt einen x:Key für DataTemplate im obigen Beispiel anzugeben, können Sie deshalb wie folgt vorgehen:

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

Dieses DataTemplate wird automatisch auf alle Task-Objekte angewendet. Beachten Sie, dass x:Key in diesem Fall implizit festgelegt wird. Wenn Sie also DataTemplate einen x:Key-Wert zuweisen, überschreiben Sie den impliziten x:Key, und DataTemplate wird nicht automatisch angewendet.

Wenn Sie ein ContentControl an eine Auflistung von Task-Objekten binden, verwendet das ContentControl nicht automatisch das oben genannte DataTemplate. Dies liegt daran, dass die Bindung für ein ContentControl weitere Informationen benötigt, um zwischen der Bindung für eine vollständige Auflistung und der Bindung für einzelne Objekte zu unterscheiden. Wenn das ContentControl die Auswahl eines ItemsControl-Typs nachverfolgt, können Sie die Path-Eigenschaft der ContentControl-Bindung auf "/" festlegen, um anzugeben, dass es um das aktuelle Element geht. Ein Beispiel finden Sie unter Gewusst wie: Binden an eine Auflistung und Anzeigen von Informationen auf Grundlage der Auswahl. Andernfalls müssen Sie das DataTemplate explizit angeben, indem Sie die ContentTemplate-Eigenschaft festlegen.

Die DataType-Eigenschaft ist besonders hilfreich, wenn Sie eine CompositeCollection mit verschiedenen Typen von Datenobjekten haben. Ein Beispiel finden Sie unter Gewusst wie: Implementieren von CompositeCollection.

Hinzufügen weiterer Elemente zur DataTemplate

Im Moment werden die Daten mit den notwendigen Informationen angezeigt, es sind aber definitiv noch Verbesserungen möglich. Wir wollen nun die Darstellung verbessern, indem wir eine Border, ein Grid und einige TextBlock-Elemente zur Beschreibung der angezeigten Daten hinzufügen.


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

Die folgende Bildschirmabbildung zeigt die ListBox mit dieser geänderten DataTemplate:

Bildschirmabbildung für Datenvorlagen-Beispiel

Wir können für die ListBox HorizontalContentAlignment auf Stretch festlegen, damit die Breite der Elemente die gesamte Fläche einnimmt:

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

Wenn die HorizontalContentAlignment-Eigenschaft auf Stretch festgelegt wird, sieht die ListBox folgendermaßen aus:

Bildschirmabbildung für Datenvorlagen-Beispiel

Anwenden von Eigenschaftswerten mit DataTrigger

Aus der aktuellen Darstellung geht nicht hervor, ob es sich bei einer Task um eine private oder um eine arbeitsbezogene Aufgabe handelt. Beachten Sie, dass das Task-Objekt über eine TaskType-Eigenschaft des TaskType-Typs verfügt, die eine Enumeration mit dem Home-Wert und dem Work-Wert ist.

Im folgenden Beispiel legt der DataTrigger den BorderBrush des Elements mit dem Namen border auf Yellow fest, wenn die TaskType-Eigenschaft TaskType.Home ist.

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

Jetzt sieht die Anwendung aus unserem Beispiel folgendermaßen aus. Private Aufgaben werden mit einem gelben und arbeitsbezogene Aufgaben mit einem hellblauen Rahmen angezeigt:

Bildschirmabbildung für Datenvorlagen-Beispiel

In diesem Beispiel legt der DataTrigger einen Eigenschaftswert mit einem Setter fest. Die Triggerklassen verfügen auch über die EnterActions-Eigenschaft und die ExitActions-Eigenschaft, mit denen Sie verschiedene Aktionen wie z. B. Animationen starten können. Darüber hinaus gibt es auch eine MultiDataTrigger-Klasse, mit der Sie Änderungen auf der Basis mehrerer datengebundener Eigenschaftswerte anwenden können.

Derselbe Effekt kann auch erreicht werden, indem die BorderBrush-Eigenschaft an die TaskType-Eigenschaft gebunden und die Farbe mit einem Wertkonverter anhand des TaskType-Werts zurückgegeben wird. Im Hinblick auf die Leistung ist es etwas effizienter, für diesen Effekt einen Konverter zu verwenden. Darüber hinaus beinhaltet die Erstellung eines eigenen Konverters eine höhere Flexibilität, da Sie eine eigene Logik verwenden. Für welches Verfahren Sie sich entscheiden, hängt letztlich vom entsprechenden Szenario und Ihren Vorlieben ab. Informationen zum Schreiben eines Konverters finden Sie unter IValueConverter.

Was gehört in eine DataTemplate?

Im vorherigen Beispiel haben wir den Trigger mit der DataTemplate.Triggers-Eigenschaft in die DataTemplate eingefügt Der Setter des Triggers legt den Wert der Eigenschaft eines Elements (des Border-Elements) in der DataTemplate fest. Wenn jedoch die Eigenschaften, auf die sich die Setters beziehen, keine Eigenschaften von Elementen sind, die sich in der aktuellen DataTemplate befinden, ist es möglicherweise sinnvoller, die Eigenschaften mit einem Style für die ListBoxItem-Klasse festzulegen (falls das zu bindende Steuerelement eine ListBox ist). Falls der Trigger z. B. den Opacity-Wert des Elements animieren soll, wenn mit dem Mauszeiger darauf gezeigt wird, definieren Sie die Trigger innerhalb eines ListBoxItem-Formats. Ein Beispiel finden Sie unter Einführung zum Beispiel zu Stilen und Vorlagen.

Im Allgemeinen sollten Sie beachten, dass die DataTemplate auf jedes erstellte ListBoxItem angewendet wird (weitere Informationen dazu, wie und wo sie genau angewendet wird, finden Sie auf der Seite ItemTemplate). Die DataTemplate bezieht sich nur auf die Darstellung und das Erscheinungsbild der Datenobjekte. In den meisten Fällen gehören alle anderen Aspekte der Darstellung, z. B. das Erscheinungsbild eines Elements, wenn es ausgewählt wird, oder die Anordnung der Elemente in der ListBox, nicht zur DataTemplate-Definition. Ein Beispiel finden Sie im Abschnitt Formatieren und Erstellen von Vorlagen für ItemsControl.

Auswählen einer DataTemplate anhand von Eigenschaften des Datenobjekts

Im Abschnitt Die DataType-Eigenschaft wurde erläutert, dass Sie verschiedene Datenvorlagen für verschiedene Datenobjekte definieren können. Das ist bei einer CompositeCollection verschiedener Typen oder bei Auflistungen mit Elementen verschiedener Typen besonders hilfreich. Im Abschnitt Anwenden von Eigenschaftswerten mit DataTrigger wurde gezeigt, dass Sie bei einer Auflistung mit Datenobjekten desselben Typs eine DataTemplate erstellen und Änderungen dann mithilfe von Triggern auf Basis der Eigenschaftswerte der einzelnen Datenobjekte anwenden können. Mit Triggern können Sie Eigenschaftswerte anwenden oder Animationen starten, sie verfügen jedoch nicht über die nötige Flexibilität, um die Struktur der Datenobjekte zu rekonstruieren. In manchen Szenarien müssen Sie möglicherweise eine andere DataTemplate für Datenobjekte erstellen, die zwar vom selben Typ sind, jedoch über verschiedene Eigenschaften verfügen.

Wenn z. B. ein Task-Objekt den Priority-Wert 1 hat, könnte es sinnvoll sein, ihm ein völlig anderes Erscheinungsbild zuzuweisen, um als Warnung zu dienen. In diesem Fall erstellen Sie eine DataTemplate für die Anzeige der Task-Objekte mit hoher Priorität. Fügen wir nun die folgende DataTemplate dem Abschnitt Ressourcen hinzu:

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

Beachten Sie, dass in diesem Beispiel die DataTemplate.Resources-Eigenschaft verwendet wird. Die in diesem Abschnitt definierten Ressourcen werden von den Elementen in der DataTemplate gemeinsam verwendet.

Um eine Logik bereitzustellen, mit der ausgewählt werden kann, welche DataTemplate auf der Grundlage des Priority-Werts des Datenobjekts verwendet werden soll, erstellen Sie eine Unterklasse von DataTemplateSelector, und überschreiben Sie die SelectTemplate-Methode. Im folgenden Beispiel stellt die SelectTemplate-Methode eine Logik zum Zurückgeben der entsprechenden Vorlage auf der Grundlage der Priority-Eigenschaft bereit. Die Vorlage, die zurückgegeben werden soll, wird in den Ressourcen des umschließenden Window-Elements gesucht.


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

Anschließend kann der TaskListDataTemplateSelector als Ressource deklariert werden:

<Window.Resources>


...


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


...


</Window.Resources>

Um die Vorlagenauswahlressource verwenden zu können, weisen Sie diese der ItemTemplateSelector-Eigenschaft der ListBox zu. Die ListBox ruft die SelectTemplate-Methode des TaskListDataTemplateSelector für jedes Element in der zugrunde liegenden Auflistung auf. Beim Aufruf wird das Datenobjekt als Elementparameter übergeben. Die von der Methode zurückgegebene DataTemplate wird anschließend auf das betreffende Datenobjekt angewendet.

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

Mit der Vorlagenauswahl wird die ListBox nun wie folgt angezeigt:

Bildschirmabbildung für Datenvorlagen-Beispiel

Damit ist die Erläuterung unseres Beispiels abgeschlossen. Das vollständige Beispiel finden Sie unter Einführung in das Beispiel für Datenvorlagen.

Formatierung und Vorlagen für ItemsControl

Obwohl ItemsControl nicht der einzige Steuerelementtyp ist, mit dem Sie eine DataTemplate verwenden können, gehört es zu den sehr häufigen Szenarien, ein ItemsControl an eine Auflistung zu binden. Im Abschnitt Was gehört in eine DataTemplate wurde erläutert, dass sich die Definition der DataTemplate nur auf die Darstellung der Daten beziehen sollte. Um wissen zu können, wann es nicht sinnvoll ist, eine DataTemplate zu verwenden, müssen Sie mit den verschiedenen Format- und Vorlageneigenschaften vertraut sein, die von ItemsControl bereitgestellt werden. Anhand des folgenden Beispiels soll die jeweilige Funktion dieser Eigenschaften veranschaulicht werden. Das ItemsControl in diesem Beispiel ist an dieselbe Tasks-Auflistung wie im vorherigen Beispiel gebunden. Zu Demonstrationszwecken werden die Formate und die Vorlagen in diesem Beispiel inline deklariert.

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

Im Folgenden ist eine Bildschirmaufnahme des Beispiels nach dem Rendering abgebildet:

Bildschirmabbildung für ein ItemsControl-Beispiel

Beachten Sie, dass Sie ItemTemplate anstelle von ItemTemplateSelector verwenden können. Ein Beispiel finden Sie im vorherigen Abschnitt. Gleichermaßen haben Sie die Möglichkeit, ItemContainerStyleSelector anstelle von ItemContainerStyle zu verwenden.

Zwei weitere Formateigenschaften von ItemsControl, die an dieser Stelle nicht dargestellt werden, sind GroupStyle und GroupStyleSelector.

Unterstützung hierarchischer Daten

Bisher haben wir nur erläutert, wie eine einzelne Auflistung gebunden und angezeigt wird. Manchmal kann eine Auflistung auch andere Auflistungen enthalten. Die HierarchicalDataTemplate-Klasse ist auf die Verwendung mit HeaderedItemsControl-Typen ausgelegt, um solche Daten anzuzeigen. Im folgenden Beispiel ist ListLeagueList eine Liste von League-Objekten. Jedes League-Objekt verfügt über einen Name und eine Auflistung von Division-Objekten. Jede Division verfügt über einen Name und eine Auflistung von Team-Objekten, und jedes Team-Objekt verfügt über einen 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>

Im Beispiel wird veranschaulicht, dass Sie mithilfe von HierarchicalDataTemplate auf einfache Weise Listendaten anzeigen können, die andere Listen enthalten. Im Folgenden finden Sie eine Bildschirmaufnahme des Beispiels.

Bildschirmabbildung für HierarchicalDataTemplate-Beispiel

Siehe auch

Aufgaben

Gewusst wie: Suchen von Elementen, die mit einer DataTemplate generiert wurden

Konzepte

Optimieren der Leistung: Datenbindung

Erstellen von Formaten und Vorlagen

Übersicht über Datenbindung

Übersicht über GridView-Spaltenheaderstile und -Spaltenheadervorlagen