2013-07-30 49 views
0

我使用XML元素填充TreeView控件。TreeView控件的大尺寸XML元素

这种方法工作得很好。但我的问题是,如果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(); 
    } 
} 
+0

请在后台线程控制的人口(或使用新的异步/待机模式4.5) - 这样你的UI不会冻结。 – Tim

+0

度量读取XML并分别填充TreeView。当你有数字时,看看需要什么时间。如果需要 - 寻求“虚拟树视图”的实现... –

+0

请看我的编辑,谢谢你们的帮助! – jomsk1e

回答

1

你需要做三件事。

  1. 开始装载之前,调用SuspendLayout();
  2. 一个单独的线程中加载您的XML,以避免GUI死机
  3. 更新使用类似下面
  4. 加载后示例中的GUI aross线程完成后,呼叫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(); 
     } 
    } 
} 

信贷的扩展方法去:How to update the GUI from another thread in C#?