【问题标题】:How to remove all but checked nodes and their parents in a treeview?如何在树视图中删除所有未选中的节点及其父节点?
【发布时间】:2011-05-31 21:46:14
【问题描述】:

我有一个包含任意数量节点的TreeView。用户可以检查TreeView 中的任何节点,并且只要他们单击一个按钮,我就想修剪除已检查节点及其父节点之外的所有内容。我已经设置了所有按钮,它调用了一个应该修剪节点的方法,我遇到的问题是修剪背后的逻辑。即使是伪代码也会有所帮助。我知道它需要是递归的,应该从最外面的节点开始,一直往上走,但我似乎想不出递归。

我不在乎它是直接修剪TreeView,还是创建一个我可以绑定的新List<TreeNode>

任何帮助将不胜感激,谢谢。

解决方案: InBetween 的解决方案解决了我的逻辑问题,但还有一个问题。您必须从其父节点中删除节点。所以你不能只做TreeView.Remove(node) 你必须做ParentNode.ChildNodes.Remove(node)

【问题讨论】:

    标签: c# asp.net treeview treenode


    【解决方案1】:

    有时从另一个角度看待问题会有所帮助。

    如果可能的话,你为什么不先改变树管理项目检查的逻辑:

    如果用户检查一个项目,您将不会删除该项目或其父项。因此,当用户检查一个项目时,检查树上的每个项目,直到您到达所选项目的根项目。这很容易实现。

    现在,当您修剪时,您只需遍历树(从根项开始并沿树向下移动)寻找未选中的项。您可以删除这些以及所有挂在其上的项目,而无需查看该分支下是否有选定项目。

    由于您的要求,此选项可能无效。

    【讨论】:

    • 谢谢!我最终使用了您的逻辑并使其进行,因此在检查复选框时,请检查其父级。当我加载树视图时,我让它检查保存在数据库中的所有父级,然后我删除所有未检查的父级。
    【解决方案2】:

    我必须做类似的事情,如果点击了一个孩子,就会自动选择父母。所以我想这可能会有所帮助,因为它会首先选择所有父母,然后您可以通过查找已选择(从顶部)来清理:

        private void RecursiveCheckNodesDown(TreeNodeCollection tree, bool checkedFlag)
        {
            if (tree != null) 
                foreach (TreeNode node in tree)
                    RecursiveCheckNodesDown(node.Nodes, node.Checked = checkedFlag);
        }
    
        private void RecursiveCheckNodesUp(TreeNode node, bool checkedFlag)
        {
            if( node != null )
                RecursiveCheckNodesUp(node.Parent, node.Checked = checkedFlag);
        }
    
        private void SomeTreeBeginUpdate()
        {
            SomeTree.BeginUpdate();
            SomeTree.AfterCheck -= SomeTree_AfterCheck;
        }
    
        private void SomeTreeEndUpdate()
        {
            SomeTree.AfterCheck += SomeTree_AfterCheck;
            SomeTree.EndUpdate();
        }
    
        private void SomeTree_AfterCheck(object sender, TreeViewEventArgs e)
        {
            SomeTreeBeginUpdate();
            RecursiveCheckNodesDown(e.Node.Nodes, e.Node.Checked);
            if( e.Node.Checked )
                RecursiveCheckNodesUp(e.Node.Parent, e.Node.Checked);
            SomeTreeEndUpdate();
        }
    
        this.SomeTree.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.SomeTree_AfterCheck);
    

    【讨论】:

    • 感谢您的帮助。我注意到您正在使用Windows.Forms,除非我没有正确理解它,我不能在 ASP.net 应用程序中使用它吗?
    【解决方案3】:

    这可以通过实现深度优先搜索来完成...

    类似

    //pseudocode
    bool prune(treenode t)
    {
       bool mayNotDeleteThisNode=t.isChecked;
       foreach(treenode c in t.childnodes)
       {
          if(prune(c)) mayNotDeleteThisNode=true;
       }
    
       if(!mayNotDeleteThisNode)
       {
          delete(t)
       }
    
       return mayNotDeleteThisNode;
    }
    

    【讨论】:

    • 我不确定是否可以在枚举节点集合时删除节点。不会删除从 cildNodes 中删除节点并因此修改集合?我认为您必须使用常规循环来完成,或者只需使用选定的节点创建一棵新树。
    • 因此 ... 伪代码 ... delete 也可以实现为以某种方式存储那些挂起的删除操作的函数,以便在遍历树后执行
    猜你喜欢
    • 2014-12-19
    • 1970-01-01
    • 1970-01-01
    • 2018-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-06
    • 2021-11-15
    相关资源
    最近更新 更多