none
树形结构 RRS feed

  • 问题

  • 上面是要实现的具体树形结构:

    我现在程序里面得到了一个List<TreeNode> allNodes 里面包含了所有的节点。

    里面的节点的Name属性就是FB   FBM   FBW   FBM1  FBM2  这些内容,

    怎么写一段递归的函数把这5个节点弄成一棵树,用treeview显示出来啊???

    以前我是这样实现的,记录各个节点的时候还要记录他的parentid  ,后来看了一位高手的代码之后,发现:

    人家使用有规律的编号来代替parentid的,比如说,上面的FBM1一看就知道是FBM的子节点,

    一看就知道FBM和FBW是FB的子节点

    我大概觉得他是取出所有的节点(allNodes)之后,用递归函数写出来的,到底这段代码要怎么写???

    2013年11月14日 4:47

全部回复

  • using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Forms;
    
    namespace CSharp
    {
        public partial class Form1 : Form
        {
            /// <summary>
            /// 声明一个TreeNode数组
            /// </summary>
            private List<TreeNode> nodes = new List<TreeNode>();
    
            public Form1()
            {
                InitializeComponent();
    
                //动态初始化
                nodes.Add(new TreeNode("FB"));
                nodes.Add(new TreeNode("FBM"));
                nodes.Add(new TreeNode("FBW"));
                nodes.Add(new TreeNode("FBM1"));
                nodes.Add(new TreeNode("FBM2"));
                
                //添加第一个节点
                treeView1.Nodes.Add(nodes[0]);
                //移除第一个节点
                nodes.RemoveAt(0);
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                //从第二个节点开始分组
                var result = from node in nodes
                             group node by node.Text.Substring(0, 3) into temp
                             select new
                             {
                                 Key = temp.Key,
                                 values=temp,
                                 Count=temp.Count()
                             };
    
                foreach (var item in result)
                {
                    //根节点先添加
                  TreeNode node =  treeView1.Nodes[0].Nodes.Add(item.Key);
                    //子节点
                    if(item.Count>1)
                    {
                        TreeNode[]subnodes = item.values.ToArray();
                        for (int i = 1; i < subnodes.Length; i++)
                        {
                            node.Nodes.Add(subnodes[i]);
                        }
                    }
                }
            }
        }
    }

    For Account Validation, please follow "Verify Account+Number" at: http://social.msdn.microsoft.com/Forums/en-us/home?forum=reportabug
    For ASP.NET Question, please ask at: http://forums.asp.net
    For other questions, you can find a specific forum and then ask at: http://stackexchange.com/sites
    Click and Donate at:http://www.freerice.com

    2013年11月14日 6:22
    版主
  • 大侠,代码里面有些地方写的太固定了,比如说:

    group node by node.Text.Substring(0, 3) into temp

    可能这里只适合我当前的编号,但是如果老板不喜欢这个编号,他要改成  F , FM  , FW  ,  FM1  , FM2的话,上面的代码还是不通用的,还有别的方法不??

    2013年11月14日 7:50
  • 最好还是你认为定义一个类,给其编号。然后用通用的算法进行分组再排序:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Forms;
    
    namespace CSharp
    {
        public partial class Form1 : Form
        {
            private class Node:TreeNode
            {
                public int ParentId { get; set; }
                public int Id { get; set; }
            }
    
            /// <summary>
            /// 声明一个TreeNode数组
            /// </summary>
            private List<Node> nodes = new List<Node>();
    
            public Form1()
            {
                InitializeComponent();
    
                //动态初始化
                nodes.Add(new Node { Text = "F", ParentId = 0, Id = 1 });
                nodes.Add(new Node { Text = "FM", ParentId = 1, Id = 2 });
                nodes.Add(new Node { Text = "FW", ParentId = 1, Id = 3 });
                nodes.Add(new Node { Text = "FM1", ParentId = 2, Id = 4 });
                nodes.Add(new Node { Text = "FM2", ParentId = 2, Id = 5 });
                nodes.Add(new Node { Text = "FW1", ParentId = 3, Id = 6 });
            }
    
            private void AutoAdd(Node node)
            {
                var result = from n in nodes
                             where n.ParentId == node.Id
                             select n;
    
                    foreach (var item in result)
                    {
                        node.Nodes.Add(item);
                        AutoAdd(item);
                    }
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                AutoAdd(nodes[0]);
                treeView1.Nodes.Add(nodes[0]);
            }
        }
    }

    ASP.NET Question
    Other Discussions
    FreeRice Donate
    Issues to report

    2013年11月14日 8:15
    版主
  • 可能我没能表达清楚我想说的:

    我主要想这对这些字符串编码FB , FBM , FBW , FBM1  , FBM2  做一些处理,并不是手动的给他一个parentid 或者 手动的node.add(),我有一个想法:比如FBM2可以与FBM和FB匹配,最长的是FBM这个字符串,所以FMB2是FBM的子节点;FBW可以与FB做匹配,但是不能月FBM做匹配,因为  FBW.Contains(FBM)==false  ,   FBW.contains(FB)==true ,  并且FB是最长的可匹配字符串。

    我的主要思想是:   需要匹配的字符串.Contains("最长字符串")==true

    2013年11月14日 12:13
  • 比如说我写的这段代码,但是还是有错误:

        public void CreateTree(List<TreeNode> allNodes)
            {
                foreach (TreeNode nodeTmp in allNodes)
                {
                    int count = nodeTmp.Name.Length;
                    while (count >= 1)
                    {
                        //父节点的名字
                        string parentName = nodeTmp.Name.Substring(0, count - 1);
                        for (int i = 0; i < allNodes.Count; i++)
                        {
                            if (allNodes[i].Name == parentName)
                            {
                                allNodes[i].Nodes.Add(nodeTmp);
                                break;//out for 
                            }
                        }
                        //最后记得减一
                        count -= 1;
                    }//end while
                }//end foreach
    
                //找根节点
                for (int i = 0; i < allNodes.Count; i++)
                {
                    if (allNodes[i].Parent == null)
                    {
                        this.treeView2.Nodes.Add(allNodes[i]);
                    }
                }
            }//end createTree

    2013年11月14日 13:31
  • private TreeNode CreateTree(List<TreeNode> nodes)
    {
        TreeNode root = null;
        
        foreach (var node in nodes)
        {
            if (GetParentKey(node.Text, nodes) == null)
            {
                root = node;
                AddChildTreeNode(node, nodes);
            }
        }
    
        return root;
    }
    
    private void AddChildTreeNode(TreeNode parentNode, List<TreeNode> nodes)
    {
        foreach (var node in nodes)
        {
            string parentKey = GetParentKey(node.Text, nodes);
            if (node.Text != parentKey && parentNode.Text == parentKey)
            {
                AddChildTreeNode(node, nodes);
                parentNode.Nodes.Add(node);
            }
        }
    }
    
    private string GetParentKey(string nodeName, List<TreeNode> nodes)
    {
        List<string> nodeNames = nodes.Select(node => node.Text).ToList();
        foreach (var name in nodeNames.OrderByDescending(element => element.Length))
        {
            if (name != nodeName && nodeName.Contains(name))
            {
                return name;
            }
        }
        return null;
    }
    

    Test code:

    List<TreeNode> nodes = new List<TreeNode>();
    nodes.Add(new TreeNode("FB"));
    nodes.Add(new TreeNode("FBM"));
    nodes.Add(new TreeNode("FBW"));
    nodes.Add(new TreeNode("FBM1"));
    nodes.Add(new TreeNode("FBM2"));
    TreeNode node = CreateTree(nodes);
    

    2013年12月11日 7:16
  • hi

    看了好久,還不是很確定您要什麼,前後描述連貫不起來....

    您應該是要動態處理這些內容,然後變成treeView吧?

    若是的話,這跟treeView沒有關係了,而是資料結構上的處理,遊戲規則只有你知道

    建議先試著,用代碼把這些字串符分類出來,再塞到控件,否則將來老闆要求你換控件,就慘了

    比如將資料分好,然後再塞入控件

    https://msmvps.com/blogs/deborahk/archive/2009/11/09/populating-a-treeview-control-from-a-list.aspx

    http://support.microsoft.com/kb/317597

    我不會一次遞回出來,這樣UI會畫太慢,我會使用點擊節點後出來

    http://www.dotblogs.com.tw/yc421206/archive/2011/03/12/21808.aspx


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/

    2013年12月13日 3:47