【问题标题】:Delimiter-separated string to TreeView C#分隔符分隔的字符串到 TreeView C#
【发布时间】:2013-04-18 01:33:04
【问题描述】:

我有一个类似这样的输入流:

John
Peter
Vanesa
Vanesa.New
Josh
Josh.New
Josh.New.Under
...

我需要像这样向 TreeView 添加节点:

+Customers
   +John
   +Peter
   +Vanesa
      +New
   +Josh
      +New
         +Under
 ...

我有一个想法,用参数“。”分割每个字符串,但是动态加载的节点有问题。也许我必须使用某种 foreach...

我有带有记录 id 和 GroupName 的旧数据库表“组”。都充满了这些字符串。我需要创建某种“地址”,例如:John.Element 或 Vanesa.New.Element 或 Josh.New.Under.Element,其中 Element 是从其他数据表中记录的。数据库连接不是问题,问题是动态填充树

现在我已经完成了添加不包含'.'的字符串:

    reader = readGroups.ExecuteNonQuery();
    while(reader.Read())
    {
        string[] buff = reader.GetValue(1).ToString().Split('.');
        if (buff.Length == 1)
        {
            treeView1.Nodes[0].Nodes.Add(reader.GetValue(1));
        }
        else
        {
            //group contains '.'
        }
    }

编辑: 我还有一个问题。有这样的记录:John, John.New, John.Old, John.Older, John.Oldest ... 所以当AddNodes()方法运行时,方法末尾的foreach会清空John.New, John。 Old, John.Older 节点,但他们必须进入树节点 John。如果你有什么想法...

【问题讨论】:

  • 所以您有一个列表/数组/可枚举等字符串,需要将节点添加到树视图,但是您想添加子节点并且在弄清楚如何添加子节点时遇到问题?我只是不确定确切的问题是什么。
  • stackoverflow.com/questions/6280524/… 也许你需要开始使用
  • 这也是WPF还是winforms?
  • 我有旧的数据库表“组”,记录 id 和 GroupName。都充满了这些字符串。我需要创建某种“地址”,例如:John.Element 或 Vanesa.New.Element 或 Josh.New.Under.Element,其中 Element 是从其他数据表中记录的。数据库连接不是问题,问题是动态填充树...编辑...WinForms :)

标签: c# treeview delimiter treenode


【解决方案1】:

这可能主要做你想做的事,你还需要一些带有名为treeView 的 TreeView 的 xaml:

    public TreeViewItem root;

    public MainWindow()
    {
        InitializeComponent();

        root = new TreeViewItem
        {
            Header = "Customers"
        };

        treeView.Items.Add(root);

        addNode("John");
        addNode("Peter");
        addNode("Vanesa.New");
        addNode("Josh");
        addNode("Josh.New");
        addNode("Josh.New.Under");
    }

    private void addNode(string values)
    {
        var n = root;

        foreach (var val in values.Split('.'))
        {
            var isNew = true;

            foreach (var existingNode in n.Items)
            {
                if (((TreeViewItem)existingNode).Header.ToString() == val)
                {
                    n = (TreeViewItem)existingNode;
                    isNew = false;
                }
            }

            if (isNew)
            {
                var newNode = new TreeViewItem
                {
                    Header = val
                };

                n.Items.Add(newNode);

                n = newNode;
            }
        }
    }

【讨论】:

    【解决方案2】:

    对于winforms,这是您需要的。我正在使用递归在每个父节点中添加每个子节点。我已经进行了更改,以便它在开始将任何节点添加到实际树视图之前创建一个唯一节点列表

                internal class TreeNodeHierachy
        {
            public int Level { get; set; }
            public TreeNode Node { get; set; }
            public Guid Id { get; set; }
            public Guid ParentId { get; set; }
            public string RootText { get; set; }
        }
    
        private List<TreeNodeHierachy> overAllNodeList; 
    
        private void AddNodes(IEnumerable<string> data)
        {
            overAllNodeList = new List<TreeNodeHierachy>();
            foreach (var item in data)
            {
                var nodeList = new List<TreeNodeHierachy>();
                var split = item.Split('.');
                for (var i = 0; i < split.Count(); i++)
                {
                    var guid = Guid.NewGuid();
                    var parent = i == 0 ? null : nodeList.First(n => n.Level == i - 1);
                    var root = i == 0 ? null : nodeList.First(n => n.Level == 0);
                    nodeList.Add(new TreeNodeHierachy
                        {
                            Level = i,
                            Node = new TreeNode(split[i]) { Tag = guid },
                            Id = guid,
                            ParentId = parent != null ? parent.Id : Guid.Empty,
                            RootText = root != null ? root.RootText : split[i]
                        });
                }
    
                // figure out dups here
                if (!overAllNodeList.Any())
                {
                    overAllNodeList.AddRange(nodeList);
                }
                else
                {
                    nodeList = nodeList.OrderBy(x => x.Level).ToList();
                    for (var i = 0; i < nodeList.Count; i++)
                    {
    
                        var existingNode = overAllNodeList.FirstOrDefault(
                            n => n.Node.Text == nodeList[i].Node.Text && n.Level == nodeList[i].Level && n.RootText == nodeList[i].RootText);
                        if (existingNode != null && (i + 1) < nodeList.Count)
                        {
    
                            nodeList[i + 1].ParentId = existingNode.Id;
                        }
                        else
                        {
                            overAllNodeList.Add(nodeList[i]);
                        }
                    }
                }
            }
    
            foreach (var treeNodeHierachy in overAllNodeList.Where(x => x.Level == 0))
            {
                treeView1.Nodes.Add(AddChildNodes(treeNodeHierachy));
            }
        }
    
        private TreeNode AddChildNodes(TreeNodeHierachy node)
        {
            var treeNode = node.Node;
            foreach (var treeNodeHierachy in overAllNodeList.Where(n => n.ParentId == node.Id))
            {
                treeNode.Nodes.Add(AddChildNodes(treeNodeHierachy));
            }
            return treeNode;
        }
    
    
        /// <summary>
        /// Handles the Click event of the button1 control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void button1_Click(object sender, EventArgs e)
        {
            //SearchActiveDirectoryWithCriteria("(mailnickname=TM418)");
    
            var test = new List<string>
                {
                    "John",
                    "Peter",
                    "Vanesa",
                    "Vanesa.New",
                    "Josh",
                    "Josh.New",
                    "Josh.New.Under",
                    "Josh.Old"
                };
    
            AddNodes(test);           
        }
    

    【讨论】:

    • 这可能会被修改为不删除节点,而是在发现匹配表明 Vanessa 在她下面有两个节点而不是只有 1 个节点时重新使用它们。
    • 我还有一个问题。有这样的记录:John, John.New, John.Old, John.Older, John.Oldest ... 所以当AddNodes() 方法运行时,方法末尾的foreach 会清除John.New, John。 Old, John.Older 节点,但他们必须进入树节点 John。如果你有什么想法......
    • 对不起,我忘记保存我所做的更新,我已经对其进行了更改,以便它可以添加 X 个级别,并且每个级别可以在它下面有 X 个级别
    【解决方案3】:

    我遇到了同样的问题。我以这种方式解决了这个问题:

    定义一个实现树的类:

    class TreeBuilder
    {
        public int index,depth;
        public string text;
        public Dictionary<string,TreeBuilder> childs;
        public void addToTreeVeiw(System.Windows.Forms.TreeNode root, TreeBuilder tb) {
            foreach (string key in tb.childs.Keys) {
                System.Windows.Forms.TreeNode t = root.Nodes.Add(tb.childs[key].text);
                addToTreeVeiw(t, tb.childs[key]);
    
            }
        }
    }
    

    和主要部分:

    string[] lis = {"a","b","a.a","a.ab","c","cc.a","a.b.dd","samad.hah.hoh"};
                treeView1.Nodes.Clear();
                TreeBuilder Troot = new TreeBuilder();
                TreeBuilder son;
                Troot.depth = 0;
                Troot.index = 0;
                Troot.text = "root";
                Troot.childs = new Dictionary<string, TreeBuilder>();
    
                foreach (string str in lis)
                {
                    string[] seperated = str.Split('.');
                    son = Troot;
                    int index= 0;
                    for (int depth = 0; depth < seperated.Length; depth++)
                    {
                        if (son.childs.ContainsKey(seperated[depth]))
                        {
                            son = son.childs[seperated[depth]];
                        }
                        else {
                            son.childs.Add(seperated[depth],new TreeBuilder());
                            son = son.childs[seperated[depth]];
                            son.index= ++index;
                            son.depth = depth+1;
                            son.text = seperated[depth];
                            son.childs = new Dictionary<string, TreeBuilder>();
                        }
                    }
                }
                treeView1.Nodes.Add("root");
                Troot.addToTreeVeiw(treeView1.Nodes[0], Troot);
    

    我猜结果就是你想要的:

    【讨论】:

      【解决方案4】:

      回复@charles380 解决方案: 我已更新代码以使用 WPF .Net Core 树视图。

      public class TreeNodeHierarchy
          {
              public int Level { get; set; }
              public TreeViewItem Node { get; set; }
              public Guid Id { get; set; }
              public Guid ParentId { get; set; }
              public string RootText { get; set; }
          }
          public class TreeManager{
      
              public List<TreeNodeHierarchy> overAllNodeList;
      
              public void AddNodes(IEnumerable<string> data, ref TreeView treeView1)
              {
                  overAllNodeList = new List<TreeNodeHierarchy>();
                  foreach (var item in data)
                  {
                      //\test
                      var nodeList = new List<TreeNodeHierarchy>();
                      var split = item.Split('.', StringSplitOptions.RemoveEmptyEntries);
                      for (var i = 0; i < split.Count(); i++)
                      {
                          var guid = Guid.NewGuid();
                          var parent = i == 0 ? null : nodeList.First(n => n.Level == i - 1);
                          var root = i == 0 ? null : nodeList.First(n => n.Level == 0);
                          nodeList.Add(new TreeNodeHierarchy
                          {
                              Level = i,
                              Node = new TreeViewItem { Header = split[i],   Tag = guid },
                              Id = guid,
                              ParentId = parent != null ? parent.Id : Guid.Empty,
                              RootText = root != null ? root.RootText : split[i]
                          });
                      }
      
                      // figure out dups here
                      if (!overAllNodeList.Any())
                      {
                          overAllNodeList.AddRange(nodeList);
                      }
                      else
                      {
                          nodeList = nodeList.OrderBy(x => x.Level).ToList();
                          for (var i = 0; i < nodeList.Count; i++)
                          {
      
                              var existingNode = overAllNodeList.FirstOrDefault(
                                  n => n.Node.Header.ToString() == nodeList[i].Node.Header.ToString() && n.Level == nodeList[i].Level && n.RootText == nodeList[i].RootText);
      
      
                              if (existingNode != null && (i + 1) < nodeList.Count)
                              {
      
                                  nodeList[i + 1].ParentId = existingNode.Id;
                              }
                              else
                              {
                                  overAllNodeList.Add(nodeList[i]);
                              }
                          }
                      }
                  }
      
                  foreach (var treeNodeHierachy in overAllNodeList.Where(x => x.Level == 0))
                  {
                      treeView1.Items.Add(AddChildNodes(treeNodeHierachy));
                  }
              }
      
              private TreeViewItem AddChildNodes(TreeNodeHierarchy node)
              {
                  var treeNode = node.Node;
                  foreach (var treeNodeHierachy in overAllNodeList.Where(n => n.ParentId == node.Id))
                  {
                      treeNode.Items.Add(AddChildNodes(treeNodeHierachy));
                  }
                  return treeNode;
              }
          }
      }
      

      示例调用代码:

          var lstFolders= new List<string>
                  {
                      "John",
                      "Peter",
                      "Vanesa",
                      "Vanesa.New",
                      "Josh",
                      "Josh.New",
                      "Josh.New.Under",
                      "Josh.Old"
                  };
      TreeManager treeManager = new TreeManager();
      treeManager.AddNodes(lstFolders, ref tr);
      

      【讨论】:

        猜你喜欢
        • 2017-05-17
        • 2010-09-15
        • 2018-04-01
        • 1970-01-01
        • 2011-02-06
        • 2014-02-10
        • 2021-10-06
        • 2023-02-25
        • 1970-01-01
        相关资源
        最近更新 更多