Добавление узлов в TreeView в быстрый способ?

Добрый день!

Я хотел бы получить ваши предложения по этому вопросу.

Я делаю небольшой инструмент в офисе для отображения "данных иерархии продуктов" в виде дерева. Наше приложение может отображать его только в табличном виде, что делает его diffucult отслеживать, если есть какие-либо неправильные данные, расположенные в иерархии.

я смог сделать некоторую логику и отобразить данные в правильной иерархии.

но моя главная проблема здесь я имею дело с записями 100K-200K+, и определенно требуется время, чтобы сделать/назначить каждый узел и добавить его в дерево. Из моего теста средние узлы могут быть созданы в минуту-8000. Я также заметил, что использование памяти этого приложения постепенно увеличивается по мере его запуска.

я включу скриншоты структуры данных и то, как выглядит приложение, чтобы дать вам некоторое представление:

enter image description here

enter image description here

пожалуйста рассмотрим мой код ниже, и я буду очень рад узнать ваши мысли о том, как оптимизировать это. Я знаю, здесь многое нужно улучшить.

и извините за длинный пост...

кстати, я использую C# и .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(); });
            }       
        }
    }
}

3 ответов


встроенные элементы управления WinForms ограничены при работе с большими наборами данных. Насколько я помню, встроенный TreeView попытается выделить свою собственную память для каждого узла (это означает, что у вас есть копия данных плюс дополнительные метаданные для каждой из ваших записей 100K+, хотя большинство из них не будут просмотрены в данном сеансе.

У меня был большой успех, используя альтернативу TreeView с открытым исходным кодом, которая предлагает виртуальные узлы (вы не визуализируете, пока они не станут видно)

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


ключ к этому может быть следующее:

  1. Вызовите TreeView.BeginUpdate
  2. добавить / удалить несколько узлов в TreeView
  3. Вызовите TreeView.EndUpdate

Это останавливает любое рисование, которое происходит при добавлении/удалении узлов. После вызова EndUpdate весь TreeView окрашивается только один раз.

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


несколько идей...

  1. вы используете поток для получения данных, а затем добавляете каждый элемент данных в дерево с помощью Invoke. Это очень медленно. Лучше использовать поток, чтобы получить все необходимые данные, а затем добавить все узлы в дерево сразу с помощью treeView1.Узлы.AddRange().

  2. вы можете оптимизировать еще больше, переработав приложение, чтобы оно получало все данные для первого уровня узлов, а затем получало данные только для более низкого уровня узлы, когда пользователь разворачивает узел дерева.