2013-07-30 79 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#?