c#解析xml繫結treeview控制元件實現
阿新 • • 發佈:2019-01-05
<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!附上效果圖: