Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Het besturingselement TreeView biedt een handige manier om hiërarchische gegevens weer te geven. Als uw TreeView is gebonden aan een gegevensbron, biedt de eigenschap SelectedItem een handige manier om snel het geselecteerde gegevensobject op te halen. Het is meestal het beste om met het onderliggende gegevensobject te werken, maar soms moet u de gegevens die TreeViewItembevatten, programmatisch bewerken. Mogelijk moet u de TreeViewItemprogrammatisch uitvouwen of een ander item in de TreeViewselecteren.
Als u een TreeViewItem wilt zoeken die een specifiek gegevensobject bevat, moet u elk niveau van de TreeViewdoorlopen. De items in een TreeView kunnen ook worden gevirtualiseerd om de prestaties te verbeteren. In het geval dat items kunnen worden gevirtualiseerd, moet u ook een TreeViewItem realiseren om te controleren of deze het gegevensobject bevat.
Voorbeeld
Beschrijving
In het volgende voorbeeld wordt gezocht naar een TreeView naar een specifiek object en wordt het object geretourneerd dat TreeViewItembevat. Het voorbeeld zorgt ervoor dat elke TreeViewItem wordt geïnstantieerd, zodat de onderliggende items kunnen worden doorzocht. Dit voorbeeld werkt ook als de TreeView geen gevirtualiseerde items gebruikt.
Opmerking
In het volgende voorbeeld wordt elke TreeViewgebruikt, ongeacht het onderliggende gegevensmodel, en wordt elke TreeViewItem doorzocht totdat het object is gevonden. Een andere techniek die betere prestaties heeft, is door het gegevensmodel voor het opgegeven object te doorzoeken, de locatie ervan in de gegevenshiërarchie bij te houden en vervolgens de bijbehorende TreeViewItem in de TreeViewte vinden. De techniek met betere prestaties vereist echter kennis van het gegevensmodel en kan niet worden gegeneraliseerd voor een gegeven TreeView.
Code
/// <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
De vorige code is afhankelijk van een aangepaste VirtualizingStackPanel die een methode met de naam BringIntoViewbeschikbaar maakt. Met de volgende code wordt de aangepaste VirtualizingStackPanelgedefinieerd.
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
In de volgende XAML ziet u hoe u een TreeView maakt die gebruikmaakt van de aangepaste VirtualizingStackPanel.
<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>
Zie ook
- De prestaties van een TreeView- verbeteren
.NET Desktop feedback