2012-06-01 4 views
6

Dzień dobry!Jak dodać węzły w TreeView w najszybszy sposób?

Chciałbym przedstawić wasze sugestie w tej sprawie.

Tworzę małe narzędzie w biurze, aby wyświetlić "Dane hierarchii produktu" w widoku drzewa. Nasza aplikacja może wyświetlać tylko tabelarycznie, co utrudnia śledzenie, czy w hierarchii znajdują się jakieś nieprawidłowe dane.

Udało mi się wprowadzić trochę logiki i wyświetlić dane we właściwej hierarchii.

Ale mój główny problem polega na tym, że mam do czynienia z rekordami 100K-200K + i na pewno potrzeba czasu, aby utworzyć/przypisać każdy węzeł i dodać go do drzewa. Z mojego testu, średnie węzły mogą być tworzone na minutę to 8000. Zauważyłem również, że wykorzystanie pamięci tej aplikacji stopniowo zwiększa się w miarę działania.

będę obejmowały zrzuty ekranu struktury danych i co aplikacja wygląda jak dać pewne wyobrażenie:

enter image description here

enter image description here

Proszę rozważyć mój kod poniżej i będę bądź bardzo szczęśliwy, gdy znasz swoje przemyślenia na temat optymalizacji tego. Wiem, że jest tu wiele do poprawienia.

I przepraszam za długi post ...

Nawiasem mówiąc, używam C# i .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(); }); 
      }  
     } 
    } 
} 

Odpowiedz

1

Wbudowane kontrolki WinForms są ograniczone w przypadku dużych zbiorów danych. O ile sobie przypominam, wbudowany TreeView spróbuje przydzielić własną pamięć dla każdego węzła (co oznacza, że ​​masz kopię danych oraz dodatkowe metadane dla każdego z twoich rekordów 100K +, nawet jeśli większość z nich nie będzie oglądany w danej sesji.

miałem dużo sukcesów stosując TreeView alternatywę open source, która oferuje wirtualne węzły (nie czynią, aż staną się widoczne)

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

+0

dzięki Eric, sprawdzając na tym ... – yonan2236

+0

za opłatą, istnieją także różne COTS rozwiązania, które działają dobrze z dużych zbiorów danych ... –

+0

genialny pomysł! – yonan2236

2

kilka pomysłów ...

  1. Używasz wątku do pobierania danych, a następnie dodajesz każdy element danych do drzewa za pomocą Invoke. To bardzo wolno. Lepszym pomysłem jest użycie wątku, aby uzyskać wszystkie potrzebne dane, a następnie dodać wszystkie węzły do ​​drzewa jednocześnie za pomocą metody treeView1.Nodes.AddRange().

  2. Możesz zoptymalizować jeszcze więcej, zmieniając aplikację, aby uzyskać wszystkie dane dla pierwszego poziomu węzłów, a następnie pobiera dane tylko dla węzłów niższego poziomu, gdy użytkownik rozwinie węzeł drzewa.

+0

Twoja pierwsza wskazówka robi ogromną różnicę w mojej sytuacji. Dodanie 1,2 miliona węzłów do widoku drzewa było niemożliwe, dodając jeden węzeł na raz. Chociaż zajmuje to trochę czasu, a aplikacja teraz przydziela 700 MB pamięci, ładuje się i wyświetla. Możesz zobaczyć w mgr zadania, że ​​ładowanie węzłów jest o wiele szybsze pod względem przydzielania pamięci. – pleinolijf