TreeView控件的大尺寸XML元素

本文关键字:XML 元素 控件 TreeView | 更新日期: 2023-09-27 18:25:23

我正在用XML元素填充TreeView控件。

这种方法非常有效。但我的问题是,如果XML文件大小达到20MB以上,我的应用程序就会冻结。有人能帮我优化我的代码吗:

public void PopulateTreeView(string xmlPath)
{
    try
    {
        var settings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore, XmlResolver = null };
        var doc = new XmlDocument();
        using (var sr = new StreamReader(xmlPath))
        {
            using (var reader = XmlReader.Create(sr, settings))
            {
                doc.Load(reader);
                //Initialize the TreeView control.
                treeView1.Nodes.Clear();
                treeView1.Invoke((MethodInvoker)(() => treeView1.Nodes.Add(new TreeNode(doc.DocumentElement.Name)))); 
                TreeNode tNode = new TreeNode();
                tNode = treeView1.Nodes[0];
                // Populate the TreeView with the DOM nodes.
                AddNode(doc.DocumentElement, tNode);
            }
        }
    }
    catch (XmlException xmlEx)
    {
        MessageBox.Show(xmlEx.Message, Path.GetFileName(xmlPath));
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}
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];
            AddNode(xNode, tNode);
        }
    }
    else
    {
        inTreeNode.Text = (inXmlNode.OuterXml).Trim();
    }
}

非常感谢您的帮助!:)

--编辑--

我试着用backgroundWorker来做这件事,但我得到了:

"InvalidOperationException-对此控件执行的操作是从错误的线程调用"

这就是我正在尝试的:

private void frmMain_Load(object sender, EventArgs e)
{
    if (!backgroundWorker.IsBusy)
        backgroundWorker.RunWorkerAsync();
}

private void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;
    if (worker.CancellationPending)
    {
        e.Cancel = true;
    }
    else
    {
        try
        {
            // SECTION 1. Create a DOM Document and load the XML data into it.
            var settings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore, XmlResolver = null };
            var doc = new XmlDocument();
            using (var sr = new StreamReader(_xmlPath))
            {
                using (var reader = XmlReader.Create(sr, settings))
                {
                    doc.Load(reader);
                    // SECTION 2. Initialize the TreeView control.
                    treeView1.Nodes.Clear();
                    treeView1.Nodes.Add(new TreeNode(doc.DocumentElement.Name));
                    TreeNode tNode = new TreeNode();
                    tNode = treeView1.Nodes[0];
                    // SECTION 3. Populate the TreeView with the DOM nodes.
                    AddNode(doc.DocumentElement, tNode);
                    //treeView1.ExpandAll();
                }
            }
        }
        catch (XmlException xmlEx)
        {
            MessageBox.Show(xmlEx.Message, Path.GetFileName(_xmlPath));
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
}
public 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];
            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();
    }
}

TreeView控件的大尺寸XML元素

您需要做三件事。

  1. 加载开始前,请调用SuspendLayout();
  2. 在单独的线程中加载XML以避免GUI锁定
  3. 使用类似以下示例的方法通过线程更新gui
  4. 加载完成后,调用ResumeLayout();

跨线程扩展方法示例:

using System;
using System.Windows.Forms;
public static class ControlExtensions
{
    /// <summary>
    /// Executes the Action asynchronously on the UI thread, does not block execution on the calling thread.
    /// </summary>
    /// <param name="control"></param>
    /// <param name="code"></param>
    public static void UIThread(this Control @this, Action code)
    {
        if (@this.InvokeRequired)
        {
            @this.BeginInvoke(code);
        }
        else
        {
            code.Invoke();
        }
    }
}

扩展方法的功劳在于:如何从C#中的另一个线程更新GUI?