【问题标题】:TreeView child node populating problemTreeView 子节点填充问题
【发布时间】:2011-09-22 05:06:20
【问题描述】:

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

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

到目前为止,我已经使用 AfterSelect 事件和处理程序来实现这一点。

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

我想使用BeforeExpand。但是BeforeExpand 的问题是,如果孩子们已经有人居住,它就可以工作。在这种情况下,当我单击组时,什么也没有发生。

如何解决这个问题?

所以代码/网络链接将不胜感激。

【问题讨论】:

    标签: c# treeview


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      树的标准行为是在每个文件夹/组的前面显示一个“+”,如果发现没有孩子,点击它时加号会消失,这样可以节省昂贵的“你有孩子吗”检查。

      如果您有确定节点是否有子节点的廉价方法,您也可以提供此信息。 This question 提供更多信息。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-11
        • 1970-01-01
        • 1970-01-01
        • 2016-02-06
        相关资源
        最近更新 更多