WPF TreeView:如何使用ExpandAll()方法?

46

如何在 WPF 中展开所有 TreeView 节点?在 WinForms 中有一个 ExpandAll() 方法可以实现此功能。

9个回答

104

这可能会有所帮助

<TreeView>
    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsExpanded" Value="True" />
        </Style>
    </TreeView.ItemContainerStyle>
</TreeView>

3
简单而有效!谢谢! - StinkyCat

20

使用 XAML Treeview 样式时,您必须像上面所写的那样拥有一个属性设置器:

在 Cs 文件中编写类似于此的方法,我在示例中使用了按钮,我的树视图名称为 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;
        }
    }

希望它能帮到你。


你好,你的代码只能展开所有项,无法折叠。请将 item.IsExpanded = true; 改为 item.IsExpanded = expand;。 - Hans Bäuml
1
@Hans Bäuml,没错,但问题是关于展开全部的,无论如何还是谢谢您 :) - Pierre-Olivier Pignon
1
@Pierre-OlivierPignon 是的,这个问题是关于“全部展开”的,但是你的代码是在假设“展开”状态可以是真或假的情况下编写的,然而你总是将其设置为真?!Hans 在要求你编辑固定代码方面是绝对正确的,但根据你的说法,它并不适用于正在寻找展开/折叠所有代码的人...很好! - Fireboyd78

14

WPF TreeView 类没有 ExpandAll 方法。因此,您需要循环遍历节点并将它们的 IsExpanded 属性设置为 true。


7

试试这个

private void btnExpandAll_Click(object sender, RoutedEventArgs e)
{
    foreach(var item in tvES.Items)
    {
        var tvi = item as TreeViewItem;
        if (tvi != null)
            tvi.ExpandSubtree();
    }
}

1
这是一个很好的快速解决方案,比被接受的答案更有用。 - NappingRabbit
好主意,但这只适用于项目类型为TreeViewItem的情况。当项目是模型(例如通过MVVM绑定)时,tvi始终为空,无法折叠。......作为解决方案,可以修改此代码:不要进行强制转换(var tvi = item as TreeViewItem;),而是像Pierre-Oliver那样进行操作:TreeViewItem tvi = tvES.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem; - Beauty

4

@Pierre-Olivier所提供的答案很好。

个人而言,在这种情况下,我更喜欢使用堆栈而不是递归,因为您无法确定数据的嵌套深度。更好的做法是将其作为扩展函数提供:

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);
}

我非常喜欢你使用 Stack 的方式 - 这对于需要递归的 Lambda 方法非常有效! - Fireboyd78

3
现在是2022年1月14日,我正在使用带有.net6的VS2022。 我相信在2015年至今期间,微软开发了一种名为ExpandSubTree()的新方法,它可以展开单个TreeViewItem而不是整棵树。这使事情更加容易。 CollapseAll则完全不同,因为只需要折叠第一层。
public static class TreeViewHelper
{
    public static void ExpandAll(this TreeView treeView)
    {
        foreach (var item in treeView.Items)
        {
            if (treeView.ItemContainerGenerator.ContainerFromItem(item) is TreeViewItem treeViewItem)
                treeViewItem.ExpandSubtree();
        }
    }

    public static void CollapseAll(this TreeView treeView)
    {
        foreach (var item in treeView.Items)
        {
            if (treeView.ItemContainerGenerator.ContainerFromItem(item) is TreeViewItem treeViewItem)
                treeViewItem.IsExpanded = false;
        }
    }

    public static void CollapseAll(this TreeViewItem treeViewItem)
    {
        foreach (var item in treeViewItem.Items)
        {
            if (treeViewItem.ItemContainerGenerator.ContainerFromItem(item) is TreeViewItem subTreeViewItem)
                subTreeViewItem.IsExpanded = false;
        }
    }
}

0
除了user2779123的评论,我知道这个问题早已得到解决,但我还建议将Pierre-Olivier Pignon的代码推送treeItem.IsExpanded = true;不仅要移动到null检查的范围内,而且要将其移动到ExpandAll过程中,因为它似乎是以允许树结构的展开和折叠格式编写的,并将其移动到那里将通过设计将根节点添加到此功能中。
如下面的示例所示:
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);
    }
}

ItemsControl没有.IsExpanded属性,但TreeViewItem有。 - user3424033

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();
            }
        }
    }
}

0

虽然其他解决方案可行,但有一种更简单的方法可以做到这一点,几乎是响应的混合。

public void ExpandAll(TreeView treeView)
{
    foreach (object item in treeView.Items)
        if (trvStory.ItemContainerGenerator.ContainerFromItem(item) is TreeViewItem treeItem)
            treeItem.ExpandSubtree();
}

现在,您只需要创建一个调用它的方法:
private void btnExpandAll_Click(object sender, RoutedEventArgs e)
{
    ExpandAll(trvItems);
}

(其中trvItems是您的TreeView的名称)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接