Data-Templates - Stelle mühelos Details deiner Objekte in WPF dar

Data-Templates - Stelle mühelos Details deiner Objekte in WPF dar

Hast du schon versucht eine Liste von Objekten in einer ListBox darzustellen? Dann weisst du bestimmt auch, dass WPF dies über die ToString Methode versucht. Obwohl das logisch ist, denn woher soll WPF nun wissen welche Daten aus deinem Objekt es wie darstellen soll, führt es häufig dazu, dass in deiner ListBox lediglich der Klassenname steht.

Damit du selber entscheiden kannst, wie die einzelnen Elemente aus einer Auflistung angezeigt werden, haben Controls wie ComboBox, ListView oder auch GridView die Eigenschaft ItemTemplate. Mit dieser kannst du definieren welches DataTemplate für jedes Element von Items verwendet werden soll.

Ein DataTemplate beschreibt also wie genau ein Element der Auflistung dargestellt wird.

Der schnellste Weg erste Resultate zu sehen ist, wenn du einfach ein DataTemplate inline an deinem Control verwendest:

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

In diesem Beispiel gibt es an deinem DataContext eine Eigenschaft mit dem Namen myTodoList. Die Objekte in der Auflistung myTodoList haben drei Eigenschaften, die an je einen TextBlock gebunden werden. Dieses Beispiel ist nun äußerst einfach. Normalerweise wird deine Aufbereitung wesentlich komplexer sein. Daher sind bei der Definition des DataTemplate deine Möglichkeiten fast unbegrenzt.

Wiederverwendbares DataTemplate

Das vorherige Beispiel begrenzt dich in den Möglichkeiten bzw. insbesondere in der Verwendung des DataTemplate. Besser ist es, wenn du das DataTemplate in einer Resource definierst. Dies kannst du sowohl in der gleichen XAML-Datei machen oder auch in einer separaten. Dann kannst du das gleiche DataTemplate sowohl für unterschiedliche Controls wie auch in unterschiedlichen Anwendungen einsetzen. Eine Möglichkeit es in einer Resource zu definieren ist so:

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

Ein so erstelltes DataTemplate kannst du dann im XAML über StaticResource wie folgt verwenden:

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

Dürfen es ein paar mehr sein?

Neben der ItemTemplate Eigenschaft haben Controls für Auflistungen die Eigenschaft ItemTemplateSelector. Dieser kannst du einen eigenen DataTemplateSelector zuweisen. Nun kannst du nicht nur ein DataTemplate verwenden, sondern gleich mehrere. Dabei entscheidet der DataTemplateSelector basierend auf Werten in den anzuzeigenden Objekten, welches DataTemplate benutzt werden soll.

Für das bisherige Beispiel könntest du sagen, dass alle Objekte mit einer Priorität gleich 1, besonders hervorgehoben werden sollen. Dazu ist es notwendig, dass du einen DataTemplateSelector mit seiner SelectTemplate Methode implementierst. Im Kontext der bisherigen Beispiele würde das dann so aussehen:

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

Für dieses Beispiel brauchst du nun zwei verschiedene DataTemplate. Eines mit dem Namen myTaskTemplate, zum Beispiel so wie in dem vorherigen Beispiel, und ein weiteres mit dem Namen importantTaskTemplate. Nun gibst du an deinem Control nicht mehr direkt ein DataTemplate über die Eigenschaft ItemTemplate an, sondern du gibst nur noch den Selector an:

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

Jetzt erstmal viel Spaß mit dem Visualisieren deiner Daten

Jan

Merke

  • Ein DataTemplate verwendest du um eine individuelle Visualisierung deiner Datenobjekte zu erstellen.
  • Insbesondere um die einzelnen Objekte einer Auflistung in Controls wie ComboBox oder GridView darzustellen, kann dir ein DataTemplate serh helfen.
  • Du definierst es am besten als Resource wie zum Beispiel innerhalb von <Window.Resources>.
  • Ein als Resource definiertes DataTemplate kannst du mit StaticResource einbinden.
  • Wenn du für eine Auflistung verschiedene DataTemplate verwenden möchtest, brauchst du einen DataTemplateSelector den du der Eigenschaft ItemTemplateSelector deines Controls übergibst.

Lernquiz

Verwende folgende Fragen, um das Gelernte von heute zu festigen:

  • Wann kommt ein DataTemplate hauptsächlich zum Einsatz?
  • Wie lautet die Syntax um ein als Resource definiertes DataTemplate mit dem Namen meinTemplate an einer ListBox zu verwenden?
  • Wozu kannst du einen DataTemplateSelector verwenden?

Am besten schaust du dir morgen und dann nochmal in ein paar Tagen die vorherigen Fragen an und beantwortest sie, ohne den Text vorher gelesen zu haben.

Weitere Informationen

  • Alle in diesem LernMoment verwendeten Beispiele stammen aus diesem MSDN-Artikel. Dort findest du auch eine umfangreichere Beschreibung.
  • Eine weitere Einführung in das Thema findest du in diesem OpenBook
comments powered by Disqus