Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Das TreeView Steuerelement bietet eine bequeme Möglichkeit zum Anzeigen hierarchischer Daten. Wenn Ihr TreeView an eine Datenquelle gebunden ist, bietet die SelectedItem Eigenschaft eine einfache Möglichkeit, das ausgewählte Datenobjekt schnell abzurufen. Es ist in der Regel am besten, mit dem zugrunde liegenden Datenobjekt zu arbeiten, aber manchmal müssen Sie die daten enthaltenden TreeViewItemDaten möglicherweise programmgesteuert bearbeiten. Möglicherweise müssen Sie das TreeViewItem programmgesteuert erweitern oder ein anderes Element in der TreeView auswählen.
Um ein TreeViewItem zu finden, das ein bestimmtes Datenobjekt enthält, müssen Sie jede Stufe von TreeView durchlaufen. Die Elemente in einer TreeView können auch virtualisiert werden, um die Leistung zu verbessern. In dem Fall, in dem Elemente virtualisiert werden können, müssen Sie auch überprüfen, ob TreeViewItem das Datenobjekt enthält.
Beispiel
BESCHREIBUNG
Im folgenden Beispiel wird in einem TreeView nach einem bestimmten Objekt gesucht, und der das Objekt enthaltende TreeViewItem wird zurückgegeben. Im Beispiel wird sichergestellt, dass jede TreeViewItem instanziiert wird, sodass ihre untergeordneten Elemente durchsucht werden können. Dieses Beispiel funktioniert auch, wenn die TreeView keine virtualisierten Elemente verwendet.
Hinweis
Das folgende Beispiel funktioniert für alle TreeView, unabhängig vom zugrunde liegenden Datenmodell und durchsucht jedes TreeViewItem , bis das Objekt gefunden wird. Eine weitere Technik mit besserer Leistung ist, das Datenmodell nach dem angegebenen Objekt zu durchsuchen, dessen Position innerhalb der Datenhierarchie nachzuverfolgen und dann das entsprechende TreeViewItem im TreeView zu finden. Die Technik, die eine bessere Leistung aufweist, erfordert jedoch Kenntnisse des Datenmodells und kann nicht für eine gegebene Art TreeViewgeneralisiert werden.
Programmcode
/// <summary>
/// Recursively search for an item in this subtree.
/// </summary>
/// <param name="container">
/// The parent ItemsControl. This can be a TreeView or a TreeViewItem.
/// </param>
/// <param name="item">
/// The item to search for.
/// </param>
/// <returns>
/// The TreeViewItem that contains the specified item.
/// </returns>
private TreeViewItem GetTreeViewItem(ItemsControl container, object item)
{
if (container != null)
{
if (container.DataContext == item)
{
return container as TreeViewItem;
}
// Expand the current container
if (container is TreeViewItem && !((TreeViewItem)container).IsExpanded)
{
container.SetValue(TreeViewItem.IsExpandedProperty, true);
}
// Try to generate the ItemsPresenter and the ItemsPanel.
// by calling ApplyTemplate. Note that in the
// virtualizing case even if the item is marked
// expanded we still need to do this step in order to
// regenerate the visuals because they may have been virtualized away.
container.ApplyTemplate();
ItemsPresenter itemsPresenter =
(ItemsPresenter)container.Template.FindName("ItemsHost", container);
if (itemsPresenter != null)
{
itemsPresenter.ApplyTemplate();
}
else
{
// The Tree template has not named the ItemsPresenter,
// so walk the descendents and find the child.
itemsPresenter = FindVisualChild<ItemsPresenter>(container);
if (itemsPresenter == null)
{
container.UpdateLayout();
itemsPresenter = FindVisualChild<ItemsPresenter>(container);
}
}
Panel itemsHostPanel = (Panel)VisualTreeHelper.GetChild(itemsPresenter, 0);
// Ensure that the generator for this panel has been created.
UIElementCollection children = itemsHostPanel.Children;
MyVirtualizingStackPanel virtualizingPanel =
itemsHostPanel as MyVirtualizingStackPanel;
for (int i = 0, count = container.Items.Count; i < count; i++)
{
TreeViewItem subContainer;
if (virtualizingPanel != null)
{
// Bring the item into view so
// that the container will be generated.
virtualizingPanel.BringIntoView(i);
subContainer =
(TreeViewItem)container.ItemContainerGenerator.
ContainerFromIndex(i);
}
else
{
subContainer =
(TreeViewItem)container.ItemContainerGenerator.
ContainerFromIndex(i);
// Bring the item into view to maintain the
// same behavior as with a virtualizing panel.
subContainer.BringIntoView();
}
if (subContainer != null)
{
// Search the next level for the object.
TreeViewItem resultContainer = GetTreeViewItem(subContainer, item);
if (resultContainer != null)
{
return resultContainer;
}
else
{
// The object is not under this TreeViewItem
// so collapse it.
subContainer.IsExpanded = false;
}
}
}
}
return null;
}
/// <summary>
/// Search for an element of a certain type in the visual tree.
/// </summary>
/// <typeparam name="T">The type of element to find.</typeparam>
/// <param name="visual">The parent element.</param>
/// <returns></returns>
private T FindVisualChild<T>(Visual visual) where T : Visual
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++)
{
Visual child = (Visual)VisualTreeHelper.GetChild(visual, i);
if (child != null)
{
T correctlyTyped = child as T;
if (correctlyTyped != null)
{
return correctlyTyped;
}
T descendent = FindVisualChild<T>(child);
if (descendent != null)
{
return descendent;
}
}
}
return null;
}
''' <summary>
''' Recursively search for an item in this subtree.
''' </summary>
''' <param name="container">
''' The parent ItemsControl. This can be a TreeView or a TreeViewItem.
''' </param>
''' <param name="item">
''' The item to search for.
''' </param>
''' <returns>
''' The TreeViewItem that contains the specified item.
''' </returns>
Private Function GetTreeViewItem(ByVal container As ItemsControl,
ByVal item As Object) As TreeViewItem
If container IsNot Nothing Then
If container.DataContext Is item Then
Return TryCast(container, TreeViewItem)
End If
' Expand the current container
If TypeOf container Is TreeViewItem AndAlso
Not DirectCast(container, TreeViewItem).IsExpanded Then
container.SetValue(TreeViewItem.IsExpandedProperty, True)
End If
' Try to generate the ItemsPresenter and the ItemsPanel.
' by calling ApplyTemplate. Note that in the
' virtualizing case, even if IsExpanded = true,
' we still need to do this step in order to
' regenerate the visuals because they may have been virtualized away.
container.ApplyTemplate()
Dim itemsPresenter As ItemsPresenter =
DirectCast(container.Template.FindName("ItemsHost", container), ItemsPresenter)
If itemsPresenter IsNot Nothing Then
itemsPresenter.ApplyTemplate()
Else
' The Tree template has not named the ItemsPresenter,
' so walk the descendents and find the child.
itemsPresenter = FindVisualChild(Of ItemsPresenter)(container)
If itemsPresenter Is Nothing Then
container.UpdateLayout()
itemsPresenter = FindVisualChild(Of ItemsPresenter)(container)
End If
End If
Dim itemsHostPanel As Panel =
DirectCast(VisualTreeHelper.GetChild(itemsPresenter, 0), Panel)
' Do this to ensure that the generator for this panel has been created.
Dim children As UIElementCollection = itemsHostPanel.Children
Dim virtualizingPanel As MyVirtualizingStackPanel =
TryCast(itemsHostPanel, MyVirtualizingStackPanel)
For index As Integer = 0 To container.Items.Count - 1
Dim subContainer As TreeViewItem
If virtualizingPanel IsNot Nothing Then
' Bring the item into view so
' that the container will be generated.
virtualizingPanel.BringIntoView(index)
subContainer =
DirectCast(container.ItemContainerGenerator.ContainerFromIndex(index),
TreeViewItem)
Else
subContainer =
DirectCast(container.ItemContainerGenerator.ContainerFromIndex(index),
TreeViewItem)
' Bring the item into view to maintain the
' same behavior as with a virtualizing panel.
subContainer.BringIntoView()
End If
If subContainer IsNot Nothing Then
' Search the next level for the object.
Dim resultContainer As TreeViewItem =
GetTreeViewItem(subContainer, item)
If resultContainer IsNot Nothing Then
Return resultContainer
Else
' The object is not under this TreeViewItem
' so collapse it.
subContainer.IsExpanded = False
End If
End If
Next
End If
Return Nothing
End Function
''' <summary>
''' Search for an element of a certain type in the visual tree.
''' </summary>
''' <typeparam name="T">The type of element to find.</typeparam>
''' <param name="visual">The parent element.</param>
''' <returns></returns>
Private Function FindVisualChild(Of T As Visual)(ByVal visual As Visual) As T
For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(visual) - 1
Dim child As Visual = DirectCast(VisualTreeHelper.GetChild(visual, i), Visual)
If child IsNot Nothing Then
Dim correctlyTyped As T = TryCast(child, T)
If correctlyTyped IsNot Nothing Then
Return correctlyTyped
End If
Dim descendent As T = FindVisualChild(Of T)(child)
If descendent IsNot Nothing Then
Return descendent
End If
End If
Next
Return Nothing
End Function
Der vorherige Code basiert auf einem benutzerdefinierten VirtualizingStackPanel Code, der eine Methode mit dem Namen BringIntoView
verfügbar macht. Der folgende Code definiert den benutzerdefinierten VirtualizingStackPanel Code.
public class MyVirtualizingStackPanel : VirtualizingStackPanel
{
/// <summary>
/// Publically expose BringIndexIntoView.
/// </summary>
public void BringIntoView(int index)
{
this.BringIndexIntoView(index);
}
}
Public Class MyVirtualizingStackPanel
Inherits VirtualizingStackPanel
''' <summary>
''' Publically expose BringIndexIntoView.
''' </summary>
Public Overloads Sub BringIntoView(ByVal index As Integer)
Me.BringIndexIntoView(index)
End Sub
End Class
Der folgende XAML-Code zeigt, wie Sie ein TreeView Objekt erstellen, das die benutzerdefinierten VirtualizingStackPanelElemente verwendet.
<TreeView VirtualizingStackPanel.IsVirtualizing="True">
<!--Use the custom class MyVirtualizingStackPanel
as the ItemsPanel for the TreeView and
TreeViewItem object.-->
<TreeView.ItemsPanel>
<ItemsPanelTemplate>
<src:MyVirtualizingStackPanel/>
</ItemsPanelTemplate>
</TreeView.ItemsPanel>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<src:MyVirtualizingStackPanel/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
Siehe auch
.NET Desktop feedback