【问题标题】:Remove Child Nodes from Parent Node从父节点中删除子节点
【发布时间】:2015-09-02 07:07:16
【问题描述】:

您好,我目前有一个TreeView,其结构如下:

  • 孩子

      • 儿童
        • 孩子
        • 儿童
          • RootN
          • 孩子N

    TreeView 结构基本上可以有 NRootNodes - NChildren 而 NRootNodes 可以有 NRoots 和 NChildren 所以基本上就像 Windows 资源管理器窗口一样。

我目前的问题是我必须得到所有的父母或根,在这种情况下 Roots / RootN 然后我必须删除他们的所有子节点,在本例中为 Child / ChildN。最后,我必须只有父节点,然后克隆它们,这样我就可以将它们移动到 TreeView 中的不同位置。

RootNodes 有一个独特的 Tag - Folder 而 ChildNodes 有另一个独特的 Tag - Calculations,正如我之前所说,我必须摆脱 Selected 中的所有 Calculations节点,因此只保留该选定节点的结构。

基本上最后我必须有这样的东西:

我有一个递归方法可以“扫描” SelectedNode 并获取所有父节点:

public  List<TreeNode> CollectParentNodes(TreeNodeCollection parentCollection, List<TreeNode> collectedNodes)
    {

        foreach (TreeNode node in parentCollection)
        {
            if (!collectedNodes.Contains(node.Parent))
            {
                collectedNodes.Add(node.Parent);
                parentNodeAdded = true;
            }

            if (node.Level != 0 && node.Tag.ToString() != Enumerations.NodeType.Calculation.ToString())
                collectedNodes.Add(node);

            if (node.Nodes.Count > 0)
                CollectParentNodes(node.Nodes, collectedNodes);
        }
        parentNodeAdded = false;
        return collectedNodes;
    }

最后我有一个包含所有父母的列表,但我面临的问题是父母也包含他们的后代,在这种情况下 计算

我已经搜索了谷歌和 StackOverFlow,但我找不到任何帮助,如果已经回答,我提前致歉。

谢谢。

【问题讨论】:

  • -您的意思是,您只想获取文件夹吗? -结果将是 List ot 树?
  • 是的 Reza,我只想获取文件夹,它应该是一个 List
  • 据我所知,您需要验证“标签”属性,该项目是“文件夹”还是“计算”。而且因为您希望树具有新结构,您需要复制原始树并从副本中删除子节点“计算”。
  • @BionicCode - 确实如此,但不知何故我无法删除 Childs。我基本上有一个 SelectedNode,其中包含它的所有结构,包括文件夹和子级等。不知何故,我需要遍历该 SelectedNode 并删除所有子级,所以最后我将只有文件夹。
  • 所以你的新树从 SelectedNode 开始忽略父树?

标签: c# .net winforms treeview


【解决方案1】:

您可以为返回 List 的 TreeView 创建扩展方法 GetAllNodes

记住在代码顶部使用using System.Linq;

public static class Extensions
{
    public static List<TreeNode> GetAllNodes(this TreeView tree)
    {
        var firstLevelNodes = tree.Nodes.Cast<TreeNode>();
        return firstLevelNodes.SelectMany(x => GetNodes(x)).Concat(firstLevelNodes).ToList();
    }

    private static IEnumerable<TreeNode> GetNodes(TreeNode node)
    {
        var nodes = node.Nodes.Cast<TreeNode>();
        return nodes.SelectMany(x => GetNodes(x)).Concat(nodes);
    }
}

而用法将是:

var result = this.treeView1.GetAllNodes().Where(x => x.Tag == "FOLDER").ToList();

请记住在代码顶部添加扩展类的命名空间,无论您想在哪里使用它。

例如,您可以将带有文件夹标签的所有节点设置为红色前景色:

var result = this.treeView1.GetAllNodes().Where(x => (x.Tag as string) == "FOLDER").ToList();
result.ForEach(x => x.ForeColor = Color.Red);

这是一个截图

【讨论】:

    【解决方案2】:

    这将创建一个以选定节点为根的新树,其中子节点仅包含标记为“文件夹”的节点。
    您需要创建一个复制构造函数(或扩展方法)来对节点进行深度复制,以防止对节点对象的操作影响您的原始树源:

    public TreeNode CollectFolderChildNodes(TreeNode selectedNode)
    {
       if (selectedNode.Tag == "Calculation")
          return null;
    
       // Get all the children that are tagged as folder
       var childRootNodes = selectedNode.Children.Where((childNode) => childNode.Tag == "Folder";
    
       // Clone root node using a copy constructor
       var newRoot = new TreeNode(selectedNode);    
       newRoot.Children.Clear();
    
       foreach (var childNode in childRootNodes)
       { 
          // Iterate over all children and add them to the new tree
          if (childNode.Children.Any())
          {       
             // Repeat steps for the children of the current child. 
             // Recursion stops when the leaf is reached                    
             newRoot.Children.Add(CollectFolderChildNodes(childNode));             
          }     
          else
          {
            // The current child item is leaf (no children)
            newRoot.Children.Add(new TreeNode(childNode)); 
          }     
       }
    
       return newRoot;
    }
    

    我认为应该这样做,但我没有测试它。但也许至少背后的想法很清楚。

    但正如我之前提到的,也许最好遍历树(使用相同的ItemsSource)并将属性(例如IsHidingCalculations)设置为true,以便只显示文件夹.当您的 IsHidingCalculations 计算结果为 true 时,您需要实现 ItemsStyle 并使用将项目 Visibility 设置为 Collapsed 的触发器。

    【讨论】:

    • 感谢您的解决方案。你的算法已经解决了这个问题,最后我得到了一个 TreeNode 链接了所有其他节点(只有父母)。
    • @BionicCode 我已经在stackoverflow.com/a/32360956/3110834 发布了我的扩展方法方法,以将树的所有节点作为 List
    • @Reza Aghaei 很干净,我喜欢。但是算法会将树弄平,他想保持原来的层次结构。所以我认为在这种情况下它不会有帮助。
    【解决方案3】:

    要克隆一个没有子节点的节点,您可以创建一个扩展方法,如下所示:

    public static TreeNode CloneWithoutChildren(this TreeNode node)
    {
        return new TreeNode(node.Text, node.ImageIndex, node.SelectedImageIndex)
        {
             Name = node.Name,
             ToolTipText = node.ToolTipText,
             Tag = node.Tag,
             Checked = node.Checked
        }
    }
    

    然后:

    collectedNodes.Add(node.CloneWithoutChildren());
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-04
      • 2021-06-11
      • 1970-01-01
      • 1970-01-01
      • 2020-08-30
      • 1970-01-01
      相关资源
      最近更新 更多