Проблема заполнения дочернего узла TreeView - PullRequest
4 голосов
/ 05 декабря 2009

Мне нужно построить огромное древовидное представление из составной таблицы базы данных с Grouping.

Grouping - это то, что мы видим в SQL Server Management Studio Express. После узла Database отображаются некоторые фиксированные папки (например, Database Diagrams, Tables, Views, Synonyms, Programmability и Security), и дочерние элементы группируются в эти папки.

До этого момента я использовал AfterSelect событие и обработчик для достижения этой цели.

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

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

Как это решить?

Так что коды / веб-ссылки приветствуются.

Ответы [ 2 ]

12 голосов
/ 05 декабря 2009

Обычно я добавляю «фиктивный дочерний узел» везде, где могут быть дочерние элементы, которые следует загружать ленивым образом. Это даст родительскому элементу знак плюс, а затем вы сможете добавить код в событие AfterExpand, где вы выполните следующее:

  • Проверьте, существует ли ровно один дочерний элемент, и является ли этот дочерний узел фиктивным узлом (вы можете использовать свойство Tag для идентификации фиктивного узла)
  • Если фиктивный узел найден, запустите поиск, чтобы получить дочерние элементы и добавьте их в родительский узел, завершите его, удалив фиктивный узел.

Обычно я даю фиктивному узлу текст типа «Загрузка данных. Пожалуйста, подождите ...» или около того, чтобы пользователь получил некоторую информацию о том, что происходит.

Обновление
Я собрал простой пример:

public class TreeViewSample : Form
{
    private TreeView _treeView;
    public TreeViewSample()
    {
        this._treeView = new System.Windows.Forms.TreeView();
        this._treeView.Location = new System.Drawing.Point(12, 12);
        this._treeView.Size = new System.Drawing.Size(200, 400);
        this._treeView.AfterExpand +=
            new TreeViewEventHandler(TreeView_AfterExpand);
        this.ClientSize = new System.Drawing.Size(224, 424);
        this.Controls.Add(this._treeView);
        this.Text = "TreeView Lazy Load Sample";
        InitializeTreeView();
    }

    void TreeView_AfterExpand(object sender, TreeViewEventArgs e)
    {
        if (e.Node.Nodes.Count == 1 && e.Node.Nodes[0].Tag == "dummy")
        {
            // this node has not yet been populated, launch a thread
            // to get the data
            ThreadPool.QueueUserWorkItem(state =>
            {
                IEnumerable<SomeClass> childItems = GetData();
                // load the data into the tree view (on the UI thread)
                _treeView.BeginInvoke((Action)delegate
                {
                    PopulateChildren(e.Node, childItems);
                });
            });
        }
    }

    private void PopulateChildren(TreeNode parent, IEnumerable<SomeClass> childItems)
    {
        TreeNode child;
        TreeNode dummy;
        TreeNode originalDummyItem = parent.Nodes[0];
        foreach (var item in childItems)
        {
            child = new TreeNode(item.Text);
            dummy = new TreeNode("Loading. Please wait...");
            dummy.Tag = "dummy";
            child.Nodes.Add(dummy);
            parent.Nodes.Add(child);
        }
        originalDummyItem.Remove();
    }

    private IEnumerable<SomeClass> GetData()
    {
        // simulate that this takes some time
        Thread.Sleep(500);
        return new List<SomeClass>
        {
            new SomeClass{Text = "One"},
            new SomeClass{Text = "Two"},
            new SomeClass{Text = "Three"}
        };
    }

    private void InitializeTreeView()
    {
        TreeNode rootNode = new TreeNode("Root");
        TreeNode dummyNode = new TreeNode("Loading. Please wait...");
        dummyNode.Tag = "dummy";
        rootNode.Nodes.Add(dummyNode);
        _treeView.Nodes.Add(rootNode);
    }
}

public class SomeClass
{
    public string Text { get; set; }
}
0 голосов
/ 05 декабря 2009

Это стандартное поведение для дерева - показывать «+» перед каждой папкой / группой, и плюс исчезает при нажатии, если обнаружено, что у него нет детей, это экономит дорогую проверку «есть ли у вас дети».

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...