本文概述
是否在寻找一种将整个XML文档呈现到Winforms的可扩展TreeView中的方法?你当然不希望遍历每个节点, 并根据节点包含的类型和数据写很多” if”, 不是吗?相反, 我们希望与你分享一种有趣的方法, 该方法如何将任何XML文件结构自动呈现到Winforms的TreeView组件中, 这将使你的生活更轻松。
在本文中, 我们将向你展示如何使用C#将整个XML文档呈现到Winforms应用程序的TreeView中。
1.了解渲染逻辑
在此示例中, 我们将有一个treeView1变量, 该变量代表通过工具箱中的拖放添加到表单的TreeView组件。第一步, 你需要创建一个包含XML字符串的变量, 可以从本地或远程源获取该变量, 因此, 基本上由你决定如何从要呈现的XML文件中检索数据。接下来, 使用创建的实例中的LoadXml方法使用你拥有的字符串XML数据创建XmlDocument的新结构。
因为我们假设你可能已经在treeView中包含了一些数据, 所以我们将使用TreeView的Nodes.Clear方法清除渲染过程之前的所有节点。现在, 你知道, 在每个XML文件上都有一个文档名称, 用于定义文件的含义, 例如:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://www.sitemaps.org/</loc>
<lastmod>2016-11-21</lastmod>
</url>
</urlset>
在先前的XML文件上, 文档名称为urlset, 以此类推。按照我们的逻辑, 我们还将添加此节点, 并且它将基本上包含文件的所有节点。这必须手动完成, 因此使用Node.Add将节点添加到treeView中, 然后将该节点存储到变量中, 该变量将作为辅助方法AddNode的参数提供:
try
{
// 1. Read XML File from a local path
string xmlString = File.ReadAllText(@"C:\Users\sdkca\Desktop\myXMLFile.xml", Encoding.UTF8);
// 2. Create a XML DOM Document and load the data into it.
XmlDocument dom = new XmlDocument();
dom.LoadXml(xmlString);
// 3. Initialize the TreeView control. treeView1 can be created dinamically
// and attached to the form or you can just drag and drop the widget from the toolbox
// into the Form.
// Clear any previous content of the widget
treeView1.Nodes.Clear();
// Create the root tree node, on any XML file the container (first root)
// will be the DocumentElement name as any content must be wrapped in some node first.
treeView1.Nodes.Add(new TreeNode(dom.DocumentElement.Name));
// 4. Create an instance of the first node in the treeview (the one that contains the DocumentElement name)
TreeNode tNode = new TreeNode();
tNode = treeView1.Nodes[0];
// 5. Populate the TreeView with the DOM nodes with the helper 'AddNode' function
this.AddNode(dom.DocumentElement, tNode);
}
catch (XmlException xmlEx)
{
MessageBox.Show(xmlEx.Message);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
辅助方法AddNode如下:
/// <summary>
/// Renders a node of XML into a TreeNode. Recursive if inside the node there are more child nodes.
/// </summary>
/// <param name="inXmlNode"></param>
/// <param name="inTreeNode"></param>
private void AddNode(XmlNode inXmlNode, TreeNode inTreeNode)
{
XmlNode xNode;
TreeNode tNode;
XmlNodeList nodeList;
// Loop through the XML nodes until the leaf is reached.
// Add the nodes to the TreeView during the looping process.
// If the node has child nodes, the function will call itself.
if (inXmlNode.HasChildNodes)
{
nodeList = inXmlNode.ChildNodes;
for (int i = 0; i <= nodeList.Count - 1; i++)
{
xNode = inXmlNode.ChildNodes[i];
inTreeNode.Nodes.Add(new TreeNode(xNode.Name));
tNode = inTreeNode.Nodes[i];
AddNode(xNode, tNode);
}
}
else
{
// Here you need to pull the data from the XmlNode based on the
// type of node, whether attribute values are required, and so forth.
inTreeNode.Text = (inXmlNode.OuterXml).Trim();
}
}
基本上, 它将每个XML节点转换为TreeView节点。
2.完整的例子
既然我们已经解释了逻辑, 我们就可以继续执行表单了。在此示例中, 我们将在表单上有2个元素, 一个TreeView即treeView1和一个按钮即button1, 我们从工具箱中拖动它们并将其手动附加到表单上。
然后, 在我们的代码中, 我们将向按钮添加一个事件侦听器, 因此, 当用户单击一个打开的文件对话框时, 将显示一个对话框, 并允许他选择一个将呈现到树视图中的XML文件:
using System;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Xml;
namespace Sandbox
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
/// <summary>
/// When the user clicks on the Load XML button, an open File Dialog will
/// appear, allowing you to pick an XML file to render in the treeview
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button1_Click(object sender, EventArgs e)
{
OpenFileDialog saveFileDialog1 = new OpenFileDialog();
saveFileDialog1.Filter = "XML Files (*.xml)|*.xml";
saveFileDialog1.FilterIndex = 2;
saveFileDialog1.RestoreDirectory = true;
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
this.RenderXMLFile(saveFileDialog1.FileName);
}
}
private void RenderXMLFile(string filepath)
{
try
{
// 1. Read XML File from a local path
string xmlString = File.ReadAllText(filepath, Encoding.UTF8);
// 2. Create a XML DOM Document and load the data into it.
XmlDocument dom = new XmlDocument();
dom.LoadXml(xmlString);
// 3. Initialize the TreeView control. treeView1 can be created dinamically
// and attached to the form or you can just drag and drop the widget from the toolbox
// into the Form.
// Clear any previous content of the widget
treeView1.Nodes.Clear();
// Create the root tree node, on any XML file the container (first root)
// will be the DocumentElement name as any content must be wrapped in some node first.
treeView1.Nodes.Add(new TreeNode(dom.DocumentElement.Name));
// 4. Create an instance of the first node in the treeview (the one that contains the DocumentElement name)
TreeNode tNode = new TreeNode();
tNode = treeView1.Nodes[0];
// 5. Populate the TreeView with the DOM nodes.
this.AddNode(dom.DocumentElement, tNode);
}
catch (XmlException xmlEx)
{
MessageBox.Show(xmlEx.Message);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
/// <summary>
/// Renders a node of XML into a TreeNode. Recursive if inside the node there are more child nodes.
/// </summary>
/// <param name="inXmlNode"></param>
/// <param name="inTreeNode"></param>
private void AddNode(XmlNode inXmlNode, TreeNode inTreeNode)
{
XmlNode xNode;
TreeNode tNode;
XmlNodeList nodeList;
int i;
// Loop through the XML nodes until the leaf is reached.
// Add the nodes to the TreeView during the looping process.
if (inXmlNode.HasChildNodes)
{
nodeList = inXmlNode.ChildNodes;
for (i = 0; i <= nodeList.Count - 1; i++)
{
xNode = inXmlNode.ChildNodes[i];
inTreeNode.Nodes.Add(new TreeNode(xNode.Name));
tNode = inTreeNode.Nodes[i];
this.AddNode(xNode, tNode);
}
}
else
{
// Here you need to pull the data from the XmlNode based on the
// type of node, whether attribute values are required, and so forth.
inTreeNode.Text = (inXmlNode.OuterXml).Trim();
}
}
}
}
如本文开头所述, 此方法适用于XML的每种结构, 只需加载一个随机文件, 它就会在Tree View中呈现。这种方法是通用的, 但可以轻松自定义, 因此你可以随意修改以添加条件以按数据和其他内容进行过滤。
编码愉快!