Dienstag, 23. November 2010

WPF Treeview Recursive Expand/Collapse

The following class contains an expansion method that allows for dynamic expansion and collapse of a WPF (untested with Silverlight, might work as well) TreeView. The second method parameter provides a way to define the depth of expansion/collapse.

public static class TreeViewExt

{

/// <summary>

/// Expands/collapses a treeview control recursively. Since for a hierarchical data template, the items will

/// only be generated when displayed - and only then can be expanded, the method attaches an event to the

/// StatusChanged event of the ItemsContainerGenerator and waits until they are in fact generated to recursively

/// call the expand method on these items.

/// </summary>

///

/// <param name="itemsControl"> ItemsControl, can be treeview or treeviewitem </param>

/// <param name="expand"> expand = false collapses, expand = true expands </param>

/// <param name="levelDepth"> for levelDepth = int.MaxValue, the entire tree will be expanded/collapsed.

/// For any other value n of levelDepth, only n levels away from the supplied itemsControl will be expanded

/// or collapsed to. </param>

public static void ExpandRecursively(this ItemsControl itemsControl, bool expand, int levelDepth)

{

// decrease level depth for next recursive call only if levelDepth != int.MaxValue

int depth = levelDepth == int.MaxValue ? levelDepth : levelDepth - 1;

// expand the item

TreeViewItem treeViewItem = itemsControl as TreeViewItem;

if (treeViewItem != null)

treeViewItem.IsExpanded = expand || levelDepth >= 0; // expand, or keep expanded when levelDepth >= 0

// continue if levelDepth is still bigger than 0, or if subitems need to be collapsed

if (levelDepth > 0 || !expand)

{

// get container generator of itemsControl

ItemContainerGenerator itemContainerGenerator = itemsControl.ItemContainerGenerator;

// if containers have already been generated, the subItems can be expanded/collapsed

if (itemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)

{

for (int i = itemsControl.Items.Count - 1; i >= 0; --i)

{

ItemsControl childControl = itemContainerGenerator.ContainerFromIndex(i) as ItemsControl;

if (childControl != null)

childControl.ExpandRecursively(expand, depth);

}

}

// otherwise, we have to wait for the containers to be generated. attach event to listen for status

else

{

EventHandler handler = null; // store in variable, so the handler can be detached

handler = new EventHandler((s, e) =>

{

if (itemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)

{

for (int i = itemsControl.Items.Count - 1; i >= 0; --i)

{

ItemsControl childControl = itemContainerGenerator.ContainerFromIndex(i) as ItemsControl;

if (childControl != null)

childControl.ExpandRecursively(expand, depth);

itemContainerGenerator.StatusChanged -= handler; // detach

}

}

});

itemContainerGenerator.StatusChanged += handler; // attach

}

}

}

}

Keine Kommentare:

Kommentar veröffentlichen