2013-07-30 4 views
0

Я заполняю элемент управления TreeView элементами XML.Элементы XML большого размера для элемента управления TreeView

Этот метод работает отлично. Но моя проблема в том, что размер файла XML достиг 20 Мбайт +, мое приложение замерзает. Может кто-то помочь мне оптимизировать мой код:

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(); 
    } 
} 

Большое спасибо за вашу помощь! :)

--EDIT--

Я пытался сделать это с 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. Update графический интерфейс aross нить, используя что-то вроде примера ниже
  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(); 
     } 
    } 
} 

Кредит на метод расширения идет в: How to update the GUI from another thread in C#?

Смежные вопросы