1. 程式人生 > >c#解析xml繫結treeview控制元件實現

c#解析xml繫結treeview控制元件實現

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"><span style="white-space:pre">	</span>向web端的api傳送http請求,得到的結果是xml格式的節點資訊,id標識節點號,pid標識該節點的父節點(0表示根),name是名字。</span>

節點資訊本來是web端通過dfs得到的。

原本的思路是:根據xml節點,解析它,構建鄰接矩陣或者鄰接表,用dfs(先序,遍歷到就新增到treeview裡去)生成treeview,c語言做演算法實現比較好搞,c#水平有限,畢竟google沒了,自己baidu做專案 = = 

換了個思路,因為api得到的xml節點順序正好是dfs得到的,因此我只要根據這個順序建立節點絕對沒問題,因為每個節點插入進去,絕對能夠找到父節點!

有思路了,直接開擼。

附上xml:

<content>
	<item>
		<id>1</id>
		<pid>0</pid>
		<name>5YiG57G7MQ==</name>
	</item>
	<item>
		<id>2</id>
		<pid>1</pid>
		<name>5YiG57G7MS0x</name>
	</item>
	<item>
		<id>3</id>
		<pid>2</pid>
		<name>5YiG57G7MS0xLTE=</name>
	</item>
	<item>
		<id>4</id>
		<pid>2</pid>
		<name>5YiG57G7MS0xLTI=</name>
	</item>
	<item>
		<id>5</id>
		<pid>1</pid>
		<name>5YiG57G7MS0y</name>
	</item>
	<item>
		<id>6</id>
		<pid>0</pid>
		<name>5YiG57G7Mg==</name>
	</item>
	<item>
		<id>9</id>
		<pid>6</pid>
		<name>5YiG57G7Mi0x</name>
	</item>
</content>

name是用base64編碼過的結果,取出來解碼就可以。

使用了一個類來定義xml的節點,便於還原節點。

附上treeNode的定義:

public class TreesNode
        {
            public TreesNode parent;

            private int id; //當前節點id

            public int Id
            {
                get { return id; }
                set { id = value; }
            }

            private int pid; //父節點 0表示根

            public int Pid
            {
                get { return pid; }
                set { pid = value; }
            }

            public string name = null;
 
            public TreesNode(int id, int pid, string name)
            {
                this.id = id;
                this.pid = pid;
                this.name = TreesNode.decriptionBase64(name); 
            }

            public static string decriptionBase64(string oralName)
            {
                byte[] outputb = Convert.FromBase64String(oralName); //base64解碼           
                string resultName = Encoding.GetEncoding("utf-8").GetString(outputb);
                return resultName; 
            }
        }

然後是解析xml生成treeNode陣列的過程,解析的時候注意邏輯就好
/// <summary>
        /// 解析xml 生成dfs需要的陣列
        /// </summary>
        /// <param name="xmlFile"></param>
        public void translateXML(string xmlFile)
        {
            int id, pid,temp;
            string name;

            XmlDocument doc = new XmlDocument();   
            doc.Load(xmlFile);   //載入Xml檔案  
            XmlElement rootElem = doc.DocumentElement;   //獲取根節點  
            XmlNodeList itemNodes = rootElem.GetElementsByTagName("item"); //獲取item子節點集合  

            //根節點先進去
            ITAMngApp.TkMng.UpLoadForm.TreeDefinition.TreesNode firstOne = new ITAMngApp.TkMng.UpLoadForm.TreeDefinition.TreesNode(0, 0, "5pyN5Yqh5Zmo");  //伺服器
            firstOne.parent = null;
            actualTreeNodes[0] = firstOne;
            countActualTreeNodes++;

            //之後所有的item節點根據xml放進陣列中去
            foreach (XmlNode node in itemNodes)
            {
                //讀取item下的id pid name

                XmlNodeList subAgeNodes = ((XmlElement)node).GetElementsByTagName("id");

                if (int.TryParse(subAgeNodes[0].InnerText, out temp) == true)
                {
                    id = temp;
                    subAgeNodes = ((XmlElement)node).GetElementsByTagName("pid");
                    if (int.TryParse(subAgeNodes[0].InnerText, out temp) == true) 
                    {
                        pid = temp;
                        subAgeNodes = ((XmlElement)node).GetElementsByTagName("name");
                        name = subAgeNodes[0].InnerText;
                        //ok!!!!生成陣列!!!! 節點的順序就是web端dfs得到的,
                        //根據 id 確定存放在 actualTreeNode 陣列的位置,通過每個物件的 pid 屬性來確定新增到對應的 treeview 節點下
                        ITAMngApp.TkMng.UpLoadForm.TreeDefinition.TreesNode tempNode = new ITAMngApp.TkMng.UpLoadForm.TreeDefinition.TreesNode(id, pid, name);
                        tempNode.parent = actualTreeNodes[pid];
                        actualTreeNodes[id] = tempNode;
                        if( tempNode.Id > countActualTreeNodes )
                        {
                            countActualTreeNodes = tempNode.Id;
                        }
                    }      
                }
          

用了陣列來儲存解析的node並且計數方便讀取。

 //存放xml讀取出來的treenode節點,先從xml讀取出來生成陣列,然後treeview根據每個節點的father為treeview來add節點
        private ITAMngApp.TkMng.UpLoadForm.TreeDefinition.TreesNode[] actualTreeNodes = new ITAMngApp.TkMng.UpLoadForm.TreeDefinition.TreesNode[50];

        //計數
        private int countActualTreeNodes = 0;

然後生成treeview即可,思路:

根據actualTreeNodes陣列,新增每個節點到treeview,根據name遍歷尋找父親節(xml是dfs得到所以父親)點然後新增(拿name遍歷陣列即可

/// <summary>
        /// 解析xml 生成dfs需要的陣列
        /// </summary>
        /// <param name="xmlFile"></param>
        public void translateXML(string xmlFile)
        {
            int id, pid,temp;
            string name;

            XmlDocument doc = new XmlDocument();   
            doc.Load(xmlFile);   //載入Xml檔案  
            XmlElement rootElem = doc.DocumentElement;   //獲取根節點  
            XmlNodeList itemNodes = rootElem.GetElementsByTagName("item"); //獲取item子節點集合  

            //根節點先進去
            ITAMngApp.TkMng.UpLoadForm.TreeDefinition.TreesNode firstOne = new ITAMngApp.TkMng.UpLoadForm.TreeDefinition.TreesNode(0, 0, "5pyN5Yqh5Zmo");  //伺服器
            firstOne.parent = null;
            actualTreeNodes[0] = firstOne;
            countActualTreeNodes++;

            //之後所有的item節點根據xml放進陣列中去
            foreach (XmlNode node in itemNodes)
            {
                //讀取item下的id pid name

                XmlNodeList subAgeNodes = ((XmlElement)node).GetElementsByTagName("id");

                if (int.TryParse(subAgeNodes[0].InnerText, out temp) == true)
                {
                    id = temp;
                    subAgeNodes = ((XmlElement)node).GetElementsByTagName("pid");
                    if (int.TryParse(subAgeNodes[0].InnerText, out temp) == true) 
                    {
                        pid = temp;
                        subAgeNodes = ((XmlElement)node).GetElementsByTagName("name");
                        name = subAgeNodes[0].InnerText;
                        //ok!!!!生成陣列!!!! 節點的順序就是web端dfs得到的,
                        //根據 id 確定存放在 actualTreeNode 陣列的位置,通過每個物件的 pid 屬性來確定新增到對應的 treeview 節點下
                        ITAMngApp.TkMng.UpLoadForm.TreeDefinition.TreesNode tempNode = new ITAMngApp.TkMng.UpLoadForm.TreeDefinition.TreesNode(id, pid, name);
                        tempNode.parent = actualTreeNodes[pid];
                        actualTreeNodes[id] = tempNode;
                        if( tempNode.Id > countActualTreeNodes )
                        {
                            countActualTreeNodes = tempNode.Id;
                        }
                    }      
                }
            }
        }

        /// <summary>
        /// 根據actualTreeNodes陣列,新增每個節點到treeview,根據name遍歷尋找父親節點然後新增(拿name遍歷陣列即可)
        /// </summary>
        public void addTreeViewNode() 
        {         
            treeViewNode.Nodes.Clear();
            treeViewNode.Nodes.Add(new TreeNode("伺服器"));     //根節點加入treeview

            for (int i = 1; i <= countActualTreeNodes; i++)
            {
                //取得當前節點 遍歷以前的所有節點找它的父節點,然後新增到父節點下面去!
                //遍歷所有treeview中的節點,尋找當前節點的父節點,插入treeview中去(根據dfs的結果,父節點一定存在)

                //currentNode為當前需要插入節點,遍歷treeviewNode中所有節點,尋找它的父親,插入父親下面!父親一定存在! 
                ITAMngApp.TkMng.UpLoadForm.TreeDefinition.TreesNode currentNode = actualTreeNodes[i];

                //更新bool
                //finish = false;

                if (currentNode == null)
                {
                    continue;
                }
                foreach (TreeNode item in treeViewNode.Nodes)
                {
                    // item是當前節點,這裡是遍歷所有treeview節點,找出actual[i]的父親,然後插入i
                    TreeNode node = GetNode(item, i);   
                    if (currentNode.parent.name == node.Text )
                    {
                        Console.WriteLine("fuck1");
                        TreeNode tempInsertOne = new TreeNode(currentNode.name);
                        treeViewNode.SelectedNode = node;                                  
                        treeViewNode.SelectedNode.Nodes.Add(tempInsertOne);

                        //node.Nodes.Add(tempInsertOne);                                    //這個add這裡有問題!
                        //finish = true;
                        break;
                    }
                    else
                    {
                        continue;
                    }
                }
            }
            treeViewNode.CollapseAll();
        }

        //遍歷子節點
        public TreeNode GetNode(TreeNode currentRoot, int currentNumber)
        {    
            if (currentRoot.Nodes.Count == 0)     //如果是根,返回  
            {
                Console.WriteLine("fuck3");
                //return currentRoot.Nodes[0];
                return treeViewNode.TopNode;   //返回定點 只會執行一次
            }
            else if (treeViewNode.Nodes.Count != 0)     //非根節點
            {
                Console.WriteLine("fuck4");
                TreeNode[] treeNodes = treeViewNode.Nodes.Find(currentRoot.Name, true);  //可以返回所有以currentRoot.test為標識的節點
                foreach (TreeNode temp in treeNodes)
                {
                    if (actualTreeNodes[currentNumber].parent.name == temp.Text)
                    {
                        return temp;
                        //temp.Nodes.Add(new TreeNode(actualTreeNodes[currentNumber].name));
                    }
                }
            }
            return currentRoot;
        }

        /// <summary>
        /// TreeViewNode點選事件相應
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void treeViewNode_AfterSelect(object sender, TreeViewEventArgs e)
        {
            string messageAfterSelect = string.Format("選中了{0}節點\n\n深度{1}的節點", treeViewNode.SelectedNode.Text, treeViewNode.SelectedNode.Level);
            MessageBox.Show(messageAfterSelect, "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
        }

成功繫結treeview!附上效果圖:

treeviewShow