43

How can I expand all TreeView nodes in WPF? In WinForms there was a ExpandAll() method which does this.

Charles
  • 48,924
  • 13
  • 96
  • 136

7 Answers7

96

This might help

<TreeView>
    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsExpanded" Value="True" />
        </Style>
    </TreeView.ItemContainerStyle>
</TreeView>
Prabu Arumugam
  • 1,837
  • 1
  • 15
  • 19
19

with XAML Treeview style you must have a property setter like that what wrote above :

In Cs file, write methods like this, in my sample i used a button and my treeview's name is myTV :

private void ExpandAll(ItemsControl items, bool expand)
    {
        foreach (object obj in items.Items)
        {
            ItemsControl childControl = items.ItemContainerGenerator.ContainerFromItem(obj) as ItemsControl;
            if (childControl != null)
            {
                ExpandAll(childControl, expand);
            }
            TreeViewItem item = childControl as TreeViewItem;
            if (item != null)
                item.IsExpanded = true;
        }
    }


    private void btnExpandAll_Click(object sender, RoutedEventArgs e)
    {

        foreach (object item in this.myTV.Items)
        {
            TreeViewItem treeItem = this.myTV.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
            if (treeItem != null)
                ExpandAll(treeItem, true);
            treeItem.IsExpanded = true;
        }
    }

hope it could help you.

  • Hi, Your code just works on expanding all, not collapsing. Change item.IsExpanded = true; to item.IsExpanded = expand; – Hans Bäuml May 21 '18 at 01:16
  • 1
    @Hans Bäuml , right, but the question was about Expand All, anyway thank you :) – Pierre-Olivier Pignon May 22 '18 at 07:28
  • @Pierre-OlivierPignon Yes, the question is about 'Expand All', but your code is written under the guise that the 'expand' state can be either true or false, yet you always set it to true?! Hans was absolutely right in asking you to edit in the fixed code, but according to you it's not meant for people who are looking for expand/collapse all code...nice! – Fireboyd78 Oct 20 '18 at 06:03
14

The WPF TreeView class does not have an ExpandAll method. Thus you'd have to loop through the nodes and set their IsExpanded properties to true.

CSharper
  • 6,439
  • 2
  • 43
  • 47
7

try this

private void btnExpandAll_Click(object sender, RoutedEventArgs e)
{
    foreach(var item in tvES.Items)
    {
        var tvi = item as TreeViewItem;
        if (tvi != null)
            tvi.ExpandSubtree();
    }
}
Artem
  • 121
  • 1
  • 2
  • 1
    this is a good fast solution, much more useful than the accepted answer. – NappingRabbit Jun 14 '18 at 16:20
  • Good idea, but this works only in the case that the items type is TreeViewItem. When the items are models (e.g. by MVVM binding) then `tvi` is always null and nothing collapes. ........ As solution this code could be modified: Instead of casting (`var tvi = item as TreeViewItem;`) do it like Pierre-Oliver: `TreeViewItem tvi = tvES.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;` – Beauty Oct 01 '20 at 05:57
2

The answer provided by @Pierre-Olivier is a good one.

Personally, I prefer to use a stack rather than recursion in circumstances such as these where you have no idea how deeply nested the data could be. Even better, it could be provided as an extension function:

public static void ExpandAll(this TreeViewItem treeViewItem, bool isExpanded = true)
{
    var stack = new Stack<TreeViewItem>(treeViewItem.Items.Cast<TreeViewItem>());
    while(stack.Count > 0)
    {
        TreeViewItem item = stack.Pop();

        foreach(var child in item.Items)
        {
            var childContainer = child as TreeViewItem;
            if(childContainer == null)
            {
                childContainer = item.ItemContainerGenerator.ContainerFromItem(child) as TreeViewItem;
            }

            stack.Push(childContainer);
        }

        item.IsExpanded = isExpanded;
    }
}

public static void CollapseAll(this TreeViewItem treeViewItem)
{
    treeViewItem.ExpandAll(false);
}
InTheZone
  • 379
  • 3
  • 6
0

In addition to user2779123's comment and I know this is long since been answered but I would also suggest that Pierre-Olivier Pignon's code push the treeItem.IsExpanded = true; not only be moved into scope of the null check but by moving it to the ExpandAll procedure as it appears to be written in a format that allows for both expansion and collapsing of the tree structure and moving this to there would add the root nodes to this functionality by design.

As per the below example:

private void ExpandAll(ItemsControl items, bool expand)
{
    items.IsExpanded = expand;
    foreach (object obj in items.Items)
    {
        ItemsControl childControl = items.ItemContainerGenerator.ContainerFromItem(obj) as ItemsControl;
        if (childControl != null)
        {
            ExpandAll(childControl, expand);
        }
        TreeViewItem item = childControl as TreeViewItem;
        if (item != null)
            item.IsExpanded = true;
    }
}


private void btnExpandAll_Click(object sender, RoutedEventArgs e)
{

    foreach (object item in this.myTV.Items)
    {
        TreeViewItem treeItem = this.myTV.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
        if (treeItem != null)
            ExpandAll(treeItem, true);
    }
}
0
    /// <summary>
    /// Collapse the TreeView.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void _collapseTreeView_button_Click(object sender, RoutedEventArgs e)
    {
        _ordersParentChild_TreeView.UpdateLayout();
        if (_ordersParentChild_TreeView.Items.Count > 0)
        {
            var rootTreeViewItem = _ordersParentChild_TreeView.Items[0] as TreeViewItem;
            if (rootTreeViewItem != null)
            {
                rootTreeViewItem.IsExpanded = false;
            }
        }
    }
    /// <summary>
    /// Expand the TreeView.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void _expandTreeView_button_Click(object sender, RoutedEventArgs e)
    {
        _ordersParentChild_TreeView.UpdateLayout();
        if(_ordersParentChild_TreeView.Items.Count > 0)
        {
            var rootTreeViewItem = _ordersParentChild_TreeView.Items[0] as TreeViewItem;
            if (rootTreeViewItem != null)
            {
                rootTreeViewItem.ExpandSubtree();
            }
        }
    }
}