2012-06-01 100 views
6

¡Buen día!Cómo agregar nodos en un TreeView de la manera más rápida?

Me gustaría recibir sus sugerencias con respecto a este asunto.

Estoy haciendo una pequeña herramienta en la oficina para mostrar "Datos de la jerarquía del producto" en una vista de árbol. Nuestra aplicación solo puede mostrarla de forma tabular, lo que hace difícil rastrear si hay datos incorrectos ubicados en la jerarquía.

Pude hacer un poco de lógica y visualizar los datos en la jerarquía correcta.

Pero mi principal problema aquí es que estoy tratando con 100K-200K + registros y definitivamente toma tiempo hacer/asignar cada nodo y agregarlo al árbol. De mi prueba, los nodos promedio se pueden crear por minuto, es 8000. También noté que el uso de la memoria de esta aplicación aumenta gradualmente a medida que se ejecuta.

voy incluyeron las capturas de pantalla de la estructura de los datos y lo que la aplicación se parece a darle una idea:

enter image description here

enter image description here

Por favor considere mi código de abajo y lo haré estar muy feliz de saber tus pensamientos sobre cómo optimizar esto. Sé que hay mucho que mejorar aquí.

Y lo siento por el largo post ...

Por cierto, estoy usando C# y .net2.0.

using System; 
using System.Collections.Generic; 
using System.Drawing; 
using System.Windows.Forms; 
using System.Data.OleDb; 
using System.Data; 
using System.IO; 
using System.Threading; 

namespace WinformAppTest 
{ 
    public partial class MainForm : Form 
    { 
     private DataSet _ds = new DataSet(); 

     public MainForm() 
     { 
      InitializeComponent(); 
     } 

     void MainFormLoad(object sender, EventArgs e) 
     { 
      PopulateDataSet(); 

      lblTotalRows.Text = _ds.Tables[0].Rows.Count.ToString(); 
     } 

     void PopulateDataSet() 
     { 
      string query = @"select * from " + "test.csv"; 
      try 
      { 
       OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\\;Extended Properties=\"Text;HDR=Yes;FMT=Delimited\""); 
       OleDbDataAdapter da = new OleDbDataAdapter(); 

       OleDbCommand cmd = new OleDbCommand(query, conn); 
       conn.Open(); 
       da.SelectCommand = cmd; 
       _ds.Clear(); 
       da.Fill(_ds, "CSV"); 

       conn.Close(); 
      } 
      catch (Exception ex) 
      { 
       MessageBox.Show(ex.GetBaseException().ToString()); 
      } 
     } 

     void BtnRunClick(object sender, EventArgs e) 
     { 
      Thread newThread1 = new Thread(MainForm.DoWork); 
      newThread1.Start(this); 
     } 

     public static void DoWork(object data) 
     { 
      MainForm form = (MainForm)data; 
      int counter = 0; 
      TreeNode[] nd; 

      foreach(DataRow row in ((MainForm)data)._ds.Tables[0].Rows) 
      { 
       TreeNode node = new TreeNode(); 
       if(row["Level Number"].ToString() == "1") 
       {   
        node.Name = row["ECC Hierarchy Code"].ToString(); 
        node.Text = row["ECC Hierarchy Code"].ToString() + ", " + row["Name"].ToString(); 

        form.Invoke((MethodInvoker)delegate { ((MainForm)data).treeView1.Nodes.Add(node); });  
       } 
       else 
       {     
        nd = ((MainForm)data).treeView1.Nodes.Find(row["Parent Code"].ToString(), true); 
        node.Name = (string)row["ECC Hierarchy Code"]; 
        node.Text = row["ECC Hierarchy Code"].ToString() + ", " + row["Name"].ToString(); 

        form.Invoke((MethodInvoker)delegate { nd[0].Nodes.Add(node); }); 
       } 

       counter++; 
       form.Invoke((MethodInvoker)delegate { ((MainForm)data).lblLoded.Text = counter.ToString(); }); 
      }  
     } 
    } 
} 

Respuesta

1

Los controles incorporados de WinForms son limitados cuando se trata de grandes conjuntos de datos. Por lo que recuerdo, el TreeView incorporado intentará asignar su propia memoria para cada nodo (lo que significa que tiene una copia de datos, más metadatos adicionales, para cada uno de sus 100K + registros, aunque la mayoría de ellos no serán se ve en una sesión determinada.

que tenían una gran cantidad de éxito en el uso de una alternativa de código abierto que ofrece TreeView nodos virtuales (que no hagan hasta que se vuelven visibles)

http://www.codeproject.com/Articles/20552/Virtual-Treeview-Implementation

+0

gracias Eric, comprobando en este ... – yonan2236

+0

Por una cuota, también hay varias soluciones COTS que funcionan bien con grandes conjuntos de datos ... –

+0

brillante idea! – yonan2236

2

algunas ideas ...

  1. Está usando un hilo para obtener los datos, luego agrega cada elemento de datos al árbol usando Invocar. Esto es muy lento Una mejor idea es usar el hilo para obtener todos los datos que necesita, luego agregue todos los nodos al árbol a la vez usando treeView1.Nodes.AddRange().

  2. Puede optimizar aún más al volver a trabajar su aplicación para que obtenga todos los datos para el primer nivel de nodos, luego solo obtiene los datos para nodos de nivel inferior cuando el usuario expande un nodo de árbol.

+0

Su primer consejo hace una gran diferencia en mi situación. Agregar 1.2 mln nodos a la vista de árbol era simplemente imposible agregar un nodo a la vez. Aunque lleva algo de tiempo, y la aplicación ahora asigna 700MB de memoria, sí carga y muestra. Puede ver en el administrador de tareas que la carga de los nodos es mucho más rápida en términos de asignación de memoria. – pleinolijf

Cuestiones relacionadas