How to add nodes to TreeView in the fastest way?

Good afternoon!

I would like to receive your suggestions on this subject.

I am making a small tool in the office to display the "Hierarchical Product Data" in a tree. Our application can only display it in tabular form, which makes it difficult to track the presence of incorrect data in the hierarchy.

I was able to do some logic and display the data in the correct hierarchy.

But my main problem here is that I am dealing with 100K-200K + entries, and it definitely takes time to make / assign each node and add it to the tree. From my test, medium nodes can be created in a minute - 8000. I also noticed that the memory usage in this application gradually increases as it starts up.

I'll talk about screenshots of the data structure and how the application looks to give you an idea:

enter image description here

enter image description here

Please review my code below and I will be very happy to know your thoughts on how to optimize this. I know that much remains to be improved.

And sorry for the long post ...

By the way, I am 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(); }); } } } } 
+6
source share
3 answers

The built-in WinForms controls are limited when working with large data sets. As far as I remember, the built-in TreeView will try to allocate its own memory for each node (this means that you have a copy of the data plus additional metadata for each of your 100K + records, although most of them will not be viewed in this session.

I have had great success using the open source TreeView alternative that offers virtual nodes (you do not render them until they become visible)

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

+1
source

The key to this may be as follows:

  • Call TreeView.BeginUpdate
  • Add / remove multiple nodes in TreeView
  • Call TreeView.EndUpdate

This stops any picture that occurs when adding / removing nodes. When EndUpdate is called, the entire TreeView is painted only once.

http://msdn.microsoft.com/en-us/library/system.windows.forms.treeview.beginupdate.aspx

+7
source

A few ideas ...

  • You use a stream to receive data, then add each data item to the tree using Invoke. It is very slow. It is best to use a stream to get all the necessary data, and then add all the nodes to the tree at once using treeView1.Nodes.AddRange ().

  • You can optimize even more by redesigning your application so that it receives all the data for the first level nodes, and then only receives data for the lower level nodes when the user expands the node tree.

+2
source

Source: https://habr.com/ru/post/917146/


All Articles