Ü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 Funktionen zur Datenvorlagenerstellung vorgestellt, wie z. B. die Auswahl von Vorlagen anhand benutzerdefinierter Logik und die Unterstützung der Anzeige hierarchischer Daten.

Voraussetzungen

Der Schwerpunkt dieses Themas liegt auf Datenvorlagenfeatures. Es bietet keine Einführung in Datenbindungskonzepte. Informationen zu grundlegende Datenbindungskonzepten finden Sie in der Übersicht über Datenbindung.

DataTemplate bezieht sich auf die Darstellung von Daten und gehört zu den zahlreichen Funktionen des Formatierungs- und Vorlagenerstellungsmodells von WPF. Eine Einführung in das Formatierungs- und Vorlagenerstellungsmodell von WPF, z. B. in die Verwendung von Style zur Festlegung von Eigenschaften in 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 XAML-Ressourcen.

Grundlegendes zu Datenvorlagen

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 Typs TaskType, wobei es sich um ein Enum mit dem mit den Werten Home und Work handelt.

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

Ohne „DataTemplate“

Ohne eine DataTemplate, sieht die ListBox derzeit wie folgt aus:

Screenshot of the Introduction to Data Templating Sample window showing the My Task List ListBox displaying the string representation SDKSample.Task for each source object.

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 die 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 override string ToString()
{
    return name.ToString();
}
Public Overrides Function ToString() As String
    Return _name.ToString()
End Function

Die ListBox sieht dann folgendermaßen aus:

Screenshot of the Introduction to Data Templating Sample window showing the My Task List ListBox displaying a list of tasks.

Das ist jedoch einschränkend und unflexibel. Außerdem können Sie beim Binden an XML-Daten ToString nicht überschreiben.

Definieren einer einfachen Datenvorlage

Die Lösung besteht darin, eine DataTemplate zu definieren. Eine Möglichkeit dafür besteht darin, die ItemTemplate-Eigenschaft der ListBox auf eine DataTemplate festzulegen. Die Angaben in der DataTemplate bilden die visuelle Struktur des Datenobjekts. Im Folgenden finden Sie ein einfaches Beispiel für eine DataTemplate. Sie geben Anweisungen, dass jedes Element als drei TextBlock-Elemente in einem StackPanel angezeigt wird. Jedes TextBlock-Element ist an eine Eigenschaft 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. Anstelle von Path=TaskName würden Sie z. B. XPath auf @TaskName festlegen (wenn TaskName ein Attribut des XML-Knotens ist).

Nun sieht die ListBox wie folgt aus:

Screenshot of the Introduction to Data Templating Sample window showing the My Task List ListBox displaying the tasks as TextBlock elements.

Erstellen der Datenvorlage als Ressource

Im obigen Beispiel haben Sie die DataTemplate inline definiert. Es ist jedoch üblicher, diese im Ressourcenabschnitt zu definieren, damit sie 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 sie nun für andere Steuerelemente verwenden, die über eine Eigenschaft verfügen, die einen DataTemplate-Typ annimmt. Wie oben dargestellt, ist es für ItemsControl-Objekte, wie z. B. ListBox, die ItemTemplate-Eigenschaft. Für ContentControl-Objekte ist es die ContentTemplate-Eigenschaft.

Die DataType-Eigenschaft

Die DataTemplate-Klasse verfügt über eine DataType-Eigenschaft, die der TargetType-Eigenschaft der Style-Klasse sehr ähnlich ist. Anstatt einen x:Key für die 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>

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

Wenn Sie ein ContentControl an eine Auflistung von Task-Objekten binden, verwendet das ContentControl nicht automatisch die 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 Binden an eine Auflistung und Anzeigen von Informationen auf Grundlage der Auswahl. Andernfalls müssen Sie die 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 Implementieren von CompositeCollection.

Hinzufügen weiterer Elemente zu DataTemplate

Im Moment werden die Daten mit den notwendigen Informationen angezeigt, es sind aber definitiv noch Verbesserungen möglich. Sie werden nun die Darstellung verbessern, indem Sie ein Border-Element, ein Grid-Element 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>

Der folgende Screenshot zeigt die ListBox mit dieser geänderten DataTemplate:

Screenshot of the Introduction to Data Templating Sample window showing the My Task List ListBox with the modified DataTemplate.

Sie können für die HorizontalContentAlignment für die ListBox 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"/>

Mit der auf Stretch festgelegten HorizontalContentAlignment-Eigenschaft sieht die ListBox nun wie folgt aus:

Screenshot of the Introduction to Data Templating Sample window showing the My Task List ListBox stretched to fit the screen horizontally.

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 Typs TaskType verfügt, die eine Enumeration mit den Werten Home und Work ist.

Im folgenden Beispiel legt DataTrigger den BorderBrush des Elements border auf Yellow fest, wenn die TaskType-Eigenschaft den Wert TaskType.Home aufweist.

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

Die Anwendung sieht jetzt folgendermaßen aus. Private Aufgaben werden mit einem gelben Rahmen und Office-Aufgaben mit einem hellblauen Rahmen angezeigt:

Screenshot of the Introduction to Data Templating Sample window showing the My Task List ListBox with the home and office task borders highlighted in color.

In diesem Beispiel verwendet der DataTrigger einen Setter, um einen Eigenschaftswert festzulegen. 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. Mit Blick auf die Leistung ist es etwas effizienter, für diesen Effekt einen Konverter zu verwenden. Darüber hinaus bietet 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 Sie den Trigger mit der DataTemplate.Triggers-Eigenschaft in die DataTemplate eingefügt. Der Setter des Triggers legt den Wert einer 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 Trigger innerhalb eines ListBoxItem-Stils. 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 angewandt wird. (Weitere Informationen dazu, wie und wo sie genau angewandt 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 in die 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 einigen 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, kann 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 Sie nun die folgende DataTemplate im Ressourcenabschnitt 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>

In diesem Beispiel wird die DataTemplate.Resources-Eigenschaft verwendet. 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 die SelectTemplate-Methode. Im folgenden Beispiel stellt die SelectTemplate-Methode Logik zum Zurückgeben der entsprechenden Vorlage auf der Grundlage des Werts der Priority-Eigenschaft bereit. Die Vorlage, die zurückgegeben werden soll, wird in den Ressourcen des umschließenden Window-Elements gesucht.

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

Wir können dann den TaskListDataTemplateSelector als Ressource deklarieren:

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

Um die Vorlagenauswahlressource verwenden zu können, weisen Sie diese der ItemTemplateSelector-Eigenschaft der ListBox hinzu. Die ListBox ruft die SelectTemplate-Methode des TaskListDataTemplateSelector der einzelnen Elemente in der zugrunde liegenden Auflistung auf. Beim Aufruf wird das Datenobjekt als Elementparameter übergeben. Die von der Methode zurückgegebene DataTemplate-Klasse wird dann auf dieses Datenobjekt angewandt.

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

Screenshot of Introduction to Data Templating Sample window showing the My Task List ListBox with the Priority 1 tasks prominently displayed with a red border.

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

Formatierung und Vorlagen für ItemsControl

Obwohl ItemsControl nicht der einzige Steuerelementtyp ist, mit dem Sie eine DataTemplate verwenden können, ist es üblich, 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 Stil- 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 sehen Sie ein Bildschirmfoto des Beispiels nach dem Rendern:

ItemsControl example screenshot

Beachten Sie, dass Sie anstelle von ItemTemplate den ItemTemplateSelector verwenden können. Ein Beispiel finden Sie im vorherigen Abschnitt. Entsprechend können Sie anstelle von ItemContainerStyle auch den ItemContainerStyleSelector verwenden.

Zwei weitere Stileigenschaften von ItemsControl, die hier nicht gezeigt werden, sind GroupStyle und GroupStyleSelector.

Unterstützung für hierarchische Daten

Bisher haben wir nur erläutert, wie eine einzelne Auflistung gebunden und angezeigt wird. Mitunter kann eine Auflistung auch andere Auflistungen enthalten. Die HierarchicalDataTemplate-Klasse soll mit HeaderedItemsControl-Typen verwendet werden, 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 TeamTeam-Objekt verfügt über einen 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>

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

HierarchicalDataTemplate sample screenshot

Siehe auch