Übersicht über Inhaltsmodelle für Steuerelemente
Aktualisiert: November 2007
In diesem Thema werden die Inhaltsmodelle erläutert, die von den Klassen verwendet werden, die vom Control erben. Das Inhaltsmodell gibt die Typen von Objekten an, die ein Steuerelement enthalten kann. In diesem Thema beschränkt sich der Begriff "Steuerelement" auf eine Klasse, die an irgendeiner Position in der Klassenhierarchie über die Control-Klasse verfügt. Die vier in diesem Thema erläuterten Inhaltsmodelle sind durch die folgenden vier Klassen definiert, die vom Control erben:
ContentControl enthält ein einzelnes Element.
HeaderedContentControl enthält einen Header und ein einzelnes Element.
ItemsControl enthält eine Auflistung von Objekten.
HeaderedItemsControl enthält einen Header und eine Auflistung von Elementen.
Diese vier Klassen fungieren für die meisten der Steuerelemente in WPF als Basisklassen. Klassen, die diese Inhaltsmodelle verwenden, können dieselben Inhaltstypen enthalten und den Inhalt auf dieselbe Weise behandeln. Jeder Objekttyp, der in ein ContentControl platziert werden kann (oder eine Klasse, die vom ContentControl erbt), kann in ein Steuerelement platziert werden, das über eins der drei anderen Inhaltsmodelle verfügt. Die folgende Abbildung zeigt ein Steuerelement von den einzelnen Inhaltsmodellen an, das ein Bild und einigen Text enthält.
Dieses Thema enthält folgende Abschnitte.
- Vorbereitungsmaßnahmen
- ContentControl
- HeaderedContentControl
- ItemsControl
- HeaderedItemsControl
- Verwandte Abschnitte
Vorbereitungsmaßnahmen
In diesem Thema wird vorausgesetzt, dass Sie über ein grundlegendes Verständnis in Bezug auf WPF verfügen und wissen, wie Steuerelemente einer Anwendung hinzugefügt werden. Weitere Informationen finden Sie unter Erste Schritte mit Windows Presentation Foundation und unter Übersicht über Steuerelemente.
ContentControl
Das einfachste der vier Inhaltsmodelle ist das ContentControl, das über eine Content-Eigenschaft verfügt. Die Content-Eigenschaft ist vom Typ Object, sodass keine Einschränkungen dafür bestehen, welche Elemente Sie in einem ContentControl hinzufügen können. Sie können entweder Extensible Application Markup Language (XAML) oder Code verwenden, um den Content festzulegen.
Die folgenden Steuerelemente verwenden das ContentControl-Inhaltsmodell:
Das folgende Beispiel veranschaulicht die Erstellung von vier Button-Steuerelementen, wobei Content auf eines der folgenden Elemente festgelegt ist:
Tipp
Die Extensible Application Markup Language (XAML)-Beispielversion könnte die <Button.Content>-Tags um den Inhalt der einzelnen Schaltflächen verwenden. Dieses Vorgehen ist jedoch nicht erforderlich. Weitere Informationen finden Sie unter Übersicht über XAML.
<!--Create a Button with a string as its content.-->
<Button>This is string content of a Button</Button>
<!--Create a Button with a DateTime object as its content.-->
<Button xmlns:sys="clr-namespace:System;assembly=mscorlib">
<sys:DateTime>2004/3/4 13:6:55</sys:DateTime>
</Button>
<!--Create a Button with a single UIElement as its content.-->
<Button>
<Rectangle Height="40" Width="40" Fill="Blue"/>
</Button>
<!--Create a Button with a panel that contains multiple objects
as its content.-->
<Button>
<StackPanel>
<Ellipse Height="40" Width="40" Fill="Blue"/>
<TextBlock TextAlignment="Center">Button</TextBlock>
</StackPanel>
</Button>
' Add a string to a button.
Dim stringContent As New Button()
stringContent.Content = "This is string content of a Button"
' Add a DateTime object to a button.
Dim objectContent As New Button()
Dim dateTime1 As New DateTime(2004, 3, 4, 13, 6, 55)
objectContent.Content = dateTime1
' Add a single UIElement to a button.
Dim uiElementContent As New Button()
Dim rect1 As New Rectangle()
rect1.Width = 40
rect1.Height = 40
rect1.Fill = Brushes.Blue
uiElementContent.Content = rect1
' Add a panel that contains multpile objects to a button.
Dim panelContent As New Button()
Dim stackPanel1 As New StackPanel()
Dim ellipse1 As New Ellipse()
Dim textBlock1 As New TextBlock()
ellipse1.Width = 40
ellipse1.Height = 40
ellipse1.Fill = Brushes.Blue
textBlock1.TextAlignment = TextAlignment.Center
textBlock1.Text = "Button"
stackPanel1.Children.Add(ellipse1)
stackPanel1.Children.Add(textBlock1)
panelContent.Content = stackPanel1
// Create a Button with a string as its content.
Button stringContent = new Button();
stringContent.Content = "This is string content of a Button";
// Create a Button with a DateTime object as its content.
Button objectContent = new Button();
DateTime dateTime1 = new DateTime(2004, 3, 4, 13, 6, 55);
objectContent.Content = dateTime1;
// Create a Button with a single UIElement as its content.
Button uiElementContent = new Button();
Rectangle rect1 = new Rectangle();
rect1.Width = 40;
rect1.Height = 40;
rect1.Fill = Brushes.Blue;
uiElementContent.Content = rect1;
// Create a Button with a panel that contains multiple objects
// as its content.
Button panelContent = new Button();
StackPanel stackPanel1 = new StackPanel();
Ellipse ellipse1 = new Ellipse();
TextBlock textBlock1 = new TextBlock();
ellipse1.Width = 40;
ellipse1.Height = 40;
ellipse1.Fill = Brushes.Blue;
textBlock1.TextAlignment = TextAlignment.Center;
textBlock1.Text = "Button";
stackPanel1.Children.Add(ellipse1);
stackPanel1.Children.Add(textBlock1);
panelContent.Content = stackPanel1;
Die folgende Abbildung stellt die vier im vorherigen Beispiel erstellten Schaltflächen dar.
HeaderedContentControl
Das HeaderedContentControl erbt die Content-Eigenschaft vom ContentControl und definiert die Header-Eigenschaft vom Typ Object. Header stellt eine Überschrift für das Steuerelement bereit. Wie die Content-Eigenschaft von einem ContentControl kann Header von einem beliebigen Typ sein. Im Lieferumfang von WPF sind drei Steuerelemente enthalten, die vom HeaderedContentControl erben:
Im folgenden Beispiel wird ein TabControl (ein ItemsControl) erstellt, das zwei TabItem-Objekte enthält. Das erste TabItem verfügt sowohl im Header als auch im Content über umfangreichen Inhalt: Für den Header ist ein StackPanel festgelegt, der eine Ellipse und einen TextBlock enthält, und für den Content ist ein StackPanel festgelegt, der einen TextBlock und eine Label enthält. Für den Header von dem zweiten TabItem ist eine Zeichenfolge festgelegt, und für den Content ist ein einzelner TextBlock festgelegt.
<TabControl>
<TabItem>
<TabItem.Header>
<StackPanel Orientation="Horizontal">
<Ellipse Width="10" Height="10" Fill="DarkGray"/>
<TextBlock>Tab 1</TextBlock>
</StackPanel>
</TabItem.Header>
<StackPanel>
<TextBlock>Enter some text</TextBlock>
<TextBox Name="textBox1" Width="50"/>
</StackPanel>
</TabItem>
<TabItem Header="Tab 2">
<!--Bind TextBlock.Text to the TextBox on the first
TabItem.-->
<TextBlock Text="{Binding ElementName=textBox1, Path=Text}"/>
</TabItem>
</TabControl>
In der folgenden Abbildung ist das im vorherigen Beispiel erstellte TabControl dargestellt.
ItemsControl
Steuerelemente, die vom ItemsControl erben, enthalten eine Auflistung von Objekten. Ein Beispiel für ein ItemsControl ist das ListBox. Sie können entweder die ItemsSource-Eigenschaft oder die Items-Eigenschaft verwenden, um ein ItemsControl aufzufüllen.
ItemsSource-Eigenschaft
Mit der ItemsSource-Eigenschaft von dem ItemsControl können Sie alle Typen verwenden, die IEnumerable als Inhalt von dem ItemsControl implementieren. ItemsSource wird in der Regel verwendet, um eine Datenerfassung anzuzeigen oder ein ItemsControl an ein Auflistungsobjekt zu binden.
Im folgenden Beispiel wird eine Klasse mit dem Namen MyData erstellt, bei der es sich um eine einfache Zeichenfolgenauflistung handelt.
Public Class MyData
Inherits ObservableCollection(Of String)
Public Sub New() '
Add("Item 1")
Add("Item 2")
Add("Item 3")
End Sub 'New
End Class 'MyData
public class MyData : ObservableCollection<string>
{
public MyData()
{
Add("Item 1");
Add("Item 2");
Add("Item 3");
}
}
Im folgenden Beispiel wird ItemsSource an MyData gebunden.
<!--Create an instance of MyData as a resource.-->
<src:MyData x:Key="dataList"/>
...
<ListBox ItemsSource="{Binding Source={StaticResource dataList}}"/>
Dim listBox1 As New ListBox()
Dim listData As New MyData()
Dim binding1 As New Binding()
binding1.Source = listData
listBox1.SetBinding(ListBox.ItemsSourceProperty, binding1)
ListBox listBox1 = new ListBox();
MyData listData = new MyData();
Binding binding1 = new Binding();
binding1.Source = listData;
listBox1.SetBinding(ListBox.ItemsSourceProperty, binding1);
In der folgenden Abbildung wird das im vorherigen Beispiel erstellte ListBox dargestellt.
Weitere Informationen über Datenbindung finden Sie unter Übersicht über Datenbindung.
Items-Eigenschaft
Wenn Sie kein Objekt verwenden möchten, das IEnumerable implementiert, um das ItemsControl aufzufüllen, können Sie mithilfe der Items-Eigenschaft Elemente hinzufügen. Die Elemente in einem ItemsControl können über Typen verfügen, die sich voneinander unterscheiden. Zum Beispiel kann ein ListBox ein Element enthalten, bei dem es sich um eine Zeichenfolge handelt, und ein anderes Element, bei dem es sich um ein Image handelt.
Tipp
Wenn die ItemsSource-Eigenschaft festgelegt ist, können Sie die Items-Eigenschaft verwenden, um die ItemCollection zu lesen, Sie können die ItemCollection jedoch nicht hinzufügen oder ändern. Wenn die ItemsSource-Eigenschaft auf einen NULL-Verweis festgelegt wird (Nothing in Visual Basic), wird die Auflistung entfernt, und die Verwendung von Items als leere ItemCollection wird wiederhergestellt.
Im folgenden Beispiel wird ein ListBox mit vier verschiedenen Typen von Elementen erstellt.
<!--Create a ListBox that contains a string, a Rectangle,
a Panel, and a DateTime object. These items can be accessed
via the Items property.-->
<ListBox xmlns:sys="clr-namespace:System;assembly=mscorlib"
Name="simpleListBox">
<!-- The <ListBox.Items> element is implicitly used.-->
This is a string in a ListBox
<sys:DateTime>2004/3/4 13:6:55</sys:DateTime>
<Rectangle Height="40" Width="40" Fill="Blue"/>
<StackPanel Name="itemToSelect">
<Ellipse Height="40" Fill="Blue"/>
<TextBlock>Text below an Ellipse</TextBlock>
</StackPanel>
<TextBlock>String in a TextBlock</TextBlock>
<!--</ListBox.Items>-->
</ListBox>
' Create a Button with a string as its content.
listBox1.Items.Add("This is a string in a ListBox")
' Create a Button with a DateTime object as its content.
Dim dateTime1 As New DateTime(2004, 3, 4, 13, 6, 55)
listBox1.Items.Add(dateTime1)
' Create a Button with a single UIElement as its content.
Dim rect1 As New Rectangle()
rect1.Width = 40
rect1.Height = 40
rect1.Fill = Brushes.Blue
listBox1.Items.Add(rect1)
' Create a Button with a panel that contains multiple objects
' as its content.
Dim ellipse1 As New Ellipse()
Dim textBlock1 As New TextBlock()
ellipse1.Width = 40
ellipse1.Height = 40
ellipse1.Fill = Brushes.Blue
textBlock1.TextAlignment = TextAlignment.Center
textBlock1.Text = "Text below an Ellipse"
stackPanel1.Children.Add(ellipse1)
stackPanel1.Children.Add(textBlock1)
listBox1.Items.Add(stackPanel1)
// Add a String to the ListBox.
listBox1.Items.Add("This is a string in a ListBox");
// Add a DateTime object to a ListBox.
DateTime dateTime1 = new DateTime(2004, 3, 4, 13, 6, 55);
listBox1.Items.Add(dateTime1);
// Add a Rectangle to the ListBox.
Rectangle rect1 = new Rectangle();
rect1.Width = 40;
rect1.Height = 40;
rect1.Fill = Brushes.Blue;
listBox1.Items.Add(rect1);
// Add a panel that contains multpile objects to the ListBox.
Ellipse ellipse1 = new Ellipse();
TextBlock textBlock1 = new TextBlock();
ellipse1.Width = 40;
ellipse1.Height = 40;
ellipse1.Fill = Brushes.Blue;
textBlock1.TextAlignment = TextAlignment.Center;
textBlock1.Text = "Text below an Ellipse";
stackPanel1.Children.Add(ellipse1);
stackPanel1.Children.Add(textBlock1);
listBox1.Items.Add(stackPanel1);
In der folgenden Abbildung wird das im vorherigen Beispiel erstellte ListBox dargestellt.
Elementcontainerklassen
Jedes ItemsControl, das im Lieferumfang von WPF enthalten ist, verfügt über eine entsprechende Klasse, die ein Element im ItemsControl darstellt. In der folgenden Tabelle werden die ItemsControl-Objekte aufgelistet, die im Lieferumfang von WPF und ihren entsprechenden Elementcontainern enthalten sind.
ItemsControl |
Elementcontainer |
---|---|
Sie können einen Elementcontainer explizit für jedes Element im ItemsControl erstellen. Dieses Vorgehen ist jedoch nicht erforderlich. Ob Sie einen Elementcontainer im ItemsControl erstellt haben, hängt zum größten Teil vom Szenario ab. Wenn Sie beispielsweise Daten an die ItemsSource-Eigenschaft binden, erstellen Sie nicht explizit einen Elementcontainer. Es ist wichtig, die folgenden Punkte zu berücksichtigen:
Der Typ der Objekte in der ItemCollection variiert abhängig davon, ob Sie einen Elementcontainer explizit erstellen.
Sie können den Elementcontainer abrufen, auch wenn Sie ihn nicht explizit erstellen.
Ein Style mit einem auf einen Elementcontainer festgelegten TargetType wird unabhängig davon angewendet, ob der Elementcontainer explizit erstellt wurde.
Das Verhalten der Eigenschaftenvererbung unterscheidet sich für implizit und explizit erstellte Elementcontainer, da nur explizit erstellte Elementcontainer Teil der logischen Struktur sind.
Im folgenden Beispiel werden die zwei ListBox-Steuerelemente erstellt, um diese Punkte darzustellen. Im Beispiel werden ListBoxItem-Objekte für das erste ListBox, nicht jedoch für das zweite ListBox erstellt. Im zweiten Fall wird ein ListBoxItem implizit für jedes Element im ListBox erstellt.
<!--Explicitly create a ListBoxItem for each item in the ListBox-->
<ListBox xmlns:sys="clr-namespace:System;assembly=mscorlib"
Name="listBoxItemListBox">
<!-- The <ListBox.Items> element is implicitly used.-->
<ListBoxItem>
This is a string in a ListBox
</ListBoxItem>
<ListBoxItem>
<sys:DateTime>2004/3/4 13:6:55</sys:DateTime>
</ListBoxItem>
<ListBoxItem>
<Rectangle Height="40" Width="40" Fill="Blue"/>
</ListBoxItem>
<ListBoxItem>
<StackPanel>
<Ellipse Height="40" Width="40" Fill="Blue"/>
<TextBlock>Text below an Ellipse</TextBlock>
</StackPanel>
</ListBoxItem>
<!--</ListBox.Items>-->
</ListBox>
...
<!--Create a ListBox that contains a string, a Rectangle,
a Panel, and a DateTime object. These items can be accessed
via the Items property.-->
<ListBox xmlns:sys="clr-namespace:System;assembly=mscorlib"
Name="simpleListBox">
<!-- The <ListBox.Items> element is implicitly used.-->
This is a string in a ListBox
<sys:DateTime>2004/3/4 13:6:55</sys:DateTime>
<Rectangle Height="40" Width="40" Fill="Blue"/>
<StackPanel Name="itemToSelect">
<Ellipse Height="40" Fill="Blue"/>
<TextBlock>Text below an Ellipse</TextBlock>
</StackPanel>
<TextBlock>String in a TextBlock</TextBlock>
<!--</ListBox.Items>-->
</ListBox>
Die ItemCollection ist für jedes ListBox unterschiedlich. Jedes Element in der Items-Eigenschaft für das erste ListBox ist ein ListBoxItem. Im zweiten ListBox handelt es sich dabei jedoch um einen anderen Typ. Im folgenden Beispiel wird dies bestätigt, indem die Elemente in beiden ListBox-Steuerelementen durchlaufen werden und der Typ jedes Elements überprüft wird.
Console.WriteLine("Items in simpleListBox:")
For Each item As Object In simpleListBox.Items
Console.WriteLine(item.GetType().ToString())
Next item
Console.WriteLine(vbCr + "Items in listBoxItemListBox:")
For Each item As Object In listBoxItemListBox.Items
Console.WriteLine(item.GetType().ToString())
Next item
End Sub 'ReportLBIs
...
'
' Items in simpleListBox:
' System.String
' System.Windows.Shapes.Rectangle
' System.Windows.Controls.StackPanel
' System.DateTime
'
' Items in listBoxItemListBox:
' System.Windows.Controls.ListBoxItem
' System.Windows.Controls.ListBoxItem
' System.Windows.Controls.ListBoxItem
' System.Windows.Controls.ListBoxItem
'
Console.WriteLine("Items in simpleListBox:");
foreach (object item in simpleListBox.Items)
{
Console.WriteLine(item.GetType().ToString());
}
Console.WriteLine("\rItems in listBoxItemListBox:");
foreach (object item in listBoxItemListBox.Items)
{
Console.WriteLine(item.GetType().ToString());
}
...
/*
Items in simpleListBox:
System.String
System.Windows.Shapes.Rectangle
System.Windows.Controls.StackPanel
System.DateTime
Items in listBoxItemListBox:
System.Windows.Controls.ListBoxItem
System.Windows.Controls.ListBoxItem
System.Windows.Controls.ListBoxItem
System.Windows.Controls.ListBoxItem
*/
In der folgenden Abbildung werden die zwei ListBox-Steuerelemente dargestellt, die im vorherigen Beispiel erstellt wurden.
Häufig benötigen Sie den Elementcontainer für ein Element, haben diesen aber nicht explizit in der Anwendung erstellt. Um den Elementcontainer abzurufen, der einem bestimmten Element zugeordnet ist, verwenden Sie die ContainerFromItem-Methode. Im folgenden Beispiel wird veranschaulicht, wie ein einem Element zugeordneter Elementcontainer abgerufen wird, wenn ein ListBoxItem nicht explizit erstellt wurde. Im Beispiel wird davon ausgegangen, dass es sich bei dem Objekt mit dem Namen itemToSelect nicht um ein ListBoxItem handelt und dass es dem ListBox, simpleListBox hinzugefügt wurde.
Dim lbi As ListBoxItem = _
CType(simpleListBox.ItemContainerGenerator.ContainerFromItem(itemToSelect), _
ListBoxItem)
If Not (lbi Is Nothing) Then
lbi.IsSelected = True
End If
ListBoxItem lbi =
simpleListBox.ItemContainerGenerator.ContainerFromItem(itemToSelect)
as ListBoxItem;
if (lbi != null)
{
lbi.IsSelected = true;
}
Stile, für die der TargetType auf einen Elementcontainer festgelegt ist, werden sowohl auf implizit als auch explizit erstellte Elementcontainer angewendet. Im folgenden Beispiel wird ein Style als Ressource für ein ListBoxItem erstellt, das die Inhalte im ListBoxItem horizontal zentriert. Wenn dieser Stil auf die ListBox-Objekte angewendet wird, werden die Elemente in den beiden ListBox-Objekten zentriert.
<!--Create a Style as a Resource.-->
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
In der folgenden Abbildung sind die zwei ListBox-Steuerelemente dargestellt, wenn der Stil aus dem vorherigen Beispiel angewendet wurde.
Die Funktionsweise der Eigenschaftenvererbung mit Stilen und Elementcontainern richtet sich nach der Strukturierung der logischen Struktur. Wenn Sie den Elementcontainer explizit erstellen, ist er Teil der logischen Struktur. Wenn Sie den Elementcontainer nicht erstellen, ist er nicht Teil der logischen Struktur. In der folgenden Abbildung ist der Unterschied in der logischen Struktur für die zwei ListBox-Steuerelemente aus dem vorherigen Beispiel dargestellt.
Objekte, die von der Visual-Klasse erben, erben Eigenschaftenwerte von ihrem logischen übergeordneten Element. Im folgenden Beispiel wird ein ListBox mit zwei TextBlock-Steuerelementen erstellt und die Foreground-Eigenschaft für das ListBox auf blau festgelegt. Der erste TextBlock, textBlock1, ist in einem explizit erstellten ListBoxItem enthalten, der zweite TextBlock, textBlock2, nicht. Im Beispiel wird darüber hinaus ein Style für ein ListBoxItem definiert, für das der Foreground von einem ListBoxItem auf grün festgelegt ist.
<!--Create a Style as a Resource.-->
<Style TargetType="ListBoxItem">
<Setter Property="Foreground" Value="Green"/>
</Style>
...
<ListBox Foreground="Blue">
<ListBoxItem>
<TextBlock Name="textBlock1">TextBlock in a ListBoxItem.</TextBlock>
</ListBoxItem>
<TextBlock Name="textBlock2">TextBlock not in a ListBoxItem.</TextBlock>
</ListBox>
In der folgenden Abbildung wird das im vorherigen Beispiel erstellte ListBox dargestellt.
Die Zeichenfolge im textBlock1 ist grün, und die Zeichenfolge im textBlock2 ist blau, da jedes TextBlock-Steuerelement die Foreground-Eigenschaft vom zugehörigen logischen übergeordneten Element erbt. Das logische übergeordnete Element von textBox1 ist das ListBoxItem, und das logische übergeordnete Element von textBox2 ist das ListBox. Weitere Informationen finden Sie unter Vererbung von Eigenschaftenwerten.
HeaderedItemsControl
Das HeaderedItemsControl erbt von der ItemsControl-Klasse. Das HeaderedItemsControl definiert die Header-Eigenschaft, die denselben Regeln wie die Header-Eigenschaft von einem HeaderedContentControl folgt. Im Lieferumfang von WPF sind drei Steuerelemente enthalten, die vom HeaderedItemsControl erben:
Im folgenden Beispiel wird ein TreeViewItem-Steuerelement erstellt. Die TreeView enthält ein einzelnes TreeViewItem, das als TreeViewItem 1 bezeichnet wird und über die folgenden Elemente verfügt:
Eine Zeichenfolge.
Ein DateTime-Objekt.
Ein TreeViewItem, das ein Rectangle im Header enthält.
Ein TreeViewItem, dessen Header-Eigenschaft auf einen StackPanel festgelegt wird, der zwei Objekte enthält.
Tipp
Im Beispiel werden explizit TreeViewItem-Objekte für die letzten zwei Elemente erstellt, da Rectangle und StackPanel von der Visual-Klasse erben. Der Standardstil für das TreeViewItem legt die Foreground-Eigenschaft fest. Die untergeordneten Objekte erben den Eigenschaftenwert von dem explizit erstellten TreeViewItem. Dies ist in der Regel das gewünschte Verhalten.
<TreeView xmlns:sys="clr-namespace:System;assembly=mscorlib"
Margin="10">
<TreeViewItem Header="TreeViewItem 1" IsExpanded="True">
TreeViewItem 1a
<sys:DateTime>2004/3/4 13:6:55</sys:DateTime>
<TreeViewItem>
<TreeViewItem.Header>
<Rectangle Height="10" Width="10" Fill="Blue"/>
</TreeViewItem.Header>
</TreeViewItem>
<TreeViewItem>
<TreeViewItem.Header>
<StackPanel Orientation="Horizontal">
<Ellipse Width="10" Height="10" Fill="DarkGray"/>
<TextBlock >TreeViewItem 1d</TextBlock>
</StackPanel>
</TreeViewItem.Header>
</TreeViewItem>
</TreeViewItem>
</TreeView>