TreeView子节点填充问题

时间:2009-12-05 09:46:14

标签: c# treeview

我需要使用Grouping从复合数据库表构建一个巨大的树视图。

Grouping是我们在SQL Server Management Studio Express中看到的。在Database节点之后,会显示一些固定文件夹(例如,Database DiagramsTablesViewsSynonymsProgrammability和{{1并且子项被分组到这些文件夹中。

到目前为止,我已使用Security事件和处理程序来实现此目的。

AfterSelect的问题是,在选择节点之前,观众无法知道是否有任何可用的孩子。这是因为,可展开的 AfterSelect 符号不可见。

我想使用plus。但BeforeExpand的问题是,如果孩子已经填充,它就有效。在这种情况下,当我点击组时,没有任何反应。

如何解决这个问题?

所以我们将非常感谢代码/网站链接。

2 个答案:

答案 0 :(得分:12)

我通常做的是在可能存在应该以懒惰方式加载的子项的地方添加“虚拟子节点”。这将使父级具有加号,然后您可以将代码添加到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; }
}

答案 1 :(得分:0)

树的标准行为是在每个文件夹/组前面显示“+”,如果发现没有子项,则点击加上消息,这可以节省昂贵的“你有孩子”检查。

或者,如果您有一种确定节点是否有子节点的便宜方法,则可以提供此信息。 This question提供了更多信息。