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
oderGridView
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 NamenmeinTemplate
an einerListBox
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