如何删除树视图中所有未选中的节点及其父节点?

发布于 2024-11-11 04:07:19 字数 498 浏览 6 评论 0原文

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

我不在乎它是否直接修剪 TreeView 或者它是否创建一个我可以绑定的新 List

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

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

I have a TreeView that contains any number of nodes. Users can check any of the nodes in the TreeView and as soon as they click a button I want to prune everything but the checked nodes and their parents. I've got the button all setup and it calls a method that should prune the nodes, the issue I am having is the logic behind the pruning. Even pseudo code would be helpful. I know it needs to be recursive and should start from the outer most nodes and work my way up, but I can't seem to come up with the recursion.

I don't care if it prunes the TreeView directly or if it creates a new List<TreeNode> that i can bind to.

Any help would be greatly appreciated, Thanks.

Solution: The solution by InBetween fixed my logic problem, but there was still one more issue. You have to delete nodes from their parent. So you can't just go do TreeView.Remove(node) you have to do ParentNode.ChildNodes.Remove(node).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

╭ゆ眷念 2024-11-18 04:07:19

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

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

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

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

也许由于您的要求,此选项无效。

Sometimes looking at a problem from another point of view helps.

Why dont you first change the logic of how the tree manages item checking if possible:

If the user checks an item you will not delete either the item nor its parents. Therefore when the user checks an item check every item up the tree until you get to the selected item's root item. That is easy to implement.

Now when you prune you just have to traverse the tree (starting from root items and moving down the tree) looking for non checked items. You can delete these and therefore all the items hanging from it without having to look if there are selected items down that branch.

Maybe this option is not valid due to your requirements.

以可爱出名 2024-11-18 04:07:19

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

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

I had to do something similar, where if a child was clicked, the parent was autoselected. So I guess this might help, as it would first select all parents, and then you can clean by looking for selected (from the top):

    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);
柠栀 2024-11-18 04:07:19

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

类似

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

this can by done by implementing a depth-first-search ...

something like

//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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文