How to Add Nodes in a TreeView in the Fastest Way?
.net-2.0, c#, winforms
Solution
The built-in WinForms controls are limited when dealing with large data sets. As far as I recall, the built-in TreeView will try to allocate it's own memory for each node (meaning that you have a copy of data, plus additional metadata, for each of your 100K+ records, even though most of them will not be viewed in a given session.
I had a great deal of success using an open source TreeView alternative that offers virtual nodes (you don't render until they become visible)
http://www.codeproject.com/Articles/20552/Virtual-Treeview-Implementation
Problem
Good day! I would like to have your suggestions with regards to this matter. I am making a small tool in the office to display "Product Hierarchy Data" into a tree view. Our application is only able to display it in a tabular way making it diffucult to trace if there's any incorrect data located in the hierarchy. I was able to make some logic and display the data in the correct hierarchy. But my main problem here is I'm dealing with 100K-200K+ records and it definitely takes time to make/assign each nodes and adding it to the tree. From my test, the average nodes can be created per minute is 8000. I also noticed that the memory usage of this application gradually increases as it runs. I'll included the screenshots of the structure of the data and what the application looks like to give you some idea: Please consider my code below and I will be very happy to know your thoughts on how to optimize this. I know there's a lot to be improved here. And sorry for the long post... By the way, I'm using C# and .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(); }); } } } } ```