如何动态填充树视图 (C#)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10814466/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 15:22:23  来源:igfitidea点击:

How to dynamically populate treeview (C#)

c#winformstreeview

提问by ixora

I have a table with 3 columns, ID, Name and ParentID. The ID column contains running number which also serves as the primary key. ID will also be the node's Nameproperties. Name column contain string that will be the treenode's Textattribute, while ParentID is a column contains the node's parent ID.

我有一个包含 3 列、ID、Name 和 ParentID 的表。ID 列包含运行号,它也用作主键。ID 也将是节点的Name属性。Name 列包含将作为 treenode 的Text属性的字符串,而 ParentID 是包含节点的父 ID 的列。

This is how my table looks like:

这是我的表的样子:

ID     Name   ParentID
======================
1      A      0
2      A1     1
3      B      0
4      C      0
5      A2     1
6      B1     3

This table shows that node A is the parent node for node A1 and A2. ParentID equals to "0" means that the node's parent is the root node (hardcoded). E.g., Node A, B and C are root node's children.

此表显示节点 A 是节点 A1 和 A2 的父节点。ParentID 等于“0”表示节点的父节点是根节点(硬编码)。例如,节点 A、B 和 C 是根节点的子节点。

I sort the rows by ParentID prior to populating the treeview. I populate the tree view using these two methods (TreeNode node here is the childnode that is being populated into the tree):

在填充树视图之前,我按 ParentID 对行进行排序。我使用这两种方法填充树视图(这里的 TreeNode 节点是被填充到树中的子节点):

    private void SearchParent(TreeView tree, String parentID, TreeNode node)
    {
        // Post: call TraverseParent method to search parent

        TreeNodeCollection collection = tree.Nodes;

        // Search parent recursively
        foreach (TreeNode n in collection)
        {
            TraverseParent(n, parentID, node);
        }
    }

    private void TraverseParent(TreeNode potentialParent, String parentID, TreeNode node)
    {
        // Post: search for parent. When parent is found add child to parent

        // am i the parent that you're looking for?
        if (parentID.CompareTo(potentialParent.Name) == 0)
        {
            // found me! i'm your parent!

            // add child to parent
            potentialParent.Nodes.Add(node);

            // update that the parent for child has been found
            parentFound = true;
        }
        else
        {
            // i'm not your parent

            // continue to look for parent recursively
            foreach (TreeNode n in potentialParent.Nodes)
            {
                TraverseParent(n, parentID, node);
            }
        }
    }

All is well until I drag-and-drop the nodes by making node A the child of node C and commit the changes to the database.

一切都很好,直到我通过使节点 A 成为节点 C 的子节点来拖放节点并将更改提交到数据库。

Now my database table looks like this:

现在我的数据库表如下所示:

ID     Name   ParentID
======================
1      A      4
2      A1     1
3      B      0
4      C      0
5      A2     1
6      B1     3

The next time I run the application, it fails to populate node A1 and A2 into the tree because it could not find their parents. This is because when I sort the rows based on ParentID prior to populating the treeview, the rows are sorted like this:

下次我运行应用程序时,它无法将节点 A1 和 A2 填充到树中,因为它找不到它们的父节点。这是因为当我在填充树视图之前根据 ParentID 对行进行排序时,这些行的排序方式如下:

ID     Name   ParentID
======================
3      B      0
4      C      0
2      A1     1
5      A2     1
6      B1     3
1      A      4

This way, my application will try to populate A1 and A2 nodes into the tree even before node A is created. Therefore the application could not find the parent for node A1 and A2.

这样,即使在创建节点 A 之前,我的应用程序也会尝试将 A1 和 A2 节点填充到树中。因此,应用程序找不到节点 A1 和 A2 的父节点。

Hence, can anyone tell me a way to fix this bug or is there a better way to dynamically populate a treeview?

因此,谁能告诉我修复这个错误的方法,或者有没有更好的方法来动态填充树视图?

Thanks.

谢谢。

回答by Viacheslav Smityukh

You should use recursion to fill it.

您应该使用递归来填充它。

The promised example:

承诺的例子:

public partial class Form1 : Form
    {
        private class ItemInfo
        {
            public int ID;
            public int ParentID;
            public string Name;
        }

        public Form1()
        {
            InitializeComponent();
            FillTreeView();
        }

        private void FillTreeView()
        {
            var items = new List<ItemInfo>()
            {
                new ItemInfo(){ID = 1, ParentID = 4, Name = "A"},
                new ItemInfo(){ID = 2, ParentID = 1, Name = "A1"},
                new ItemInfo(){ID = 3, ParentID = 0, Name = "B"},
                new ItemInfo(){ID = 4, ParentID = 0, Name = "C"},
                new ItemInfo(){ID = 5, ParentID = 1, Name = "A2"},
                new ItemInfo(){ID = 6, ParentID = 3, Name = "B1"},
            };

            FillNode(items, null);
        }

        private void FillNode(List<ItemInfo> items, TreeNode node)
        {
            var parentID = node != null
                ? (int)node.Tag
                : 0;

            var nodesCollection = node != null
                ? node.Nodes
                : treeView1.Nodes;

            foreach (var item in items.Where(i => i.ParentID == parentID))
            {
                var newNode = nodesCollection.Add(item.Name, item.Name);
                newNode.Tag = item.ID;

                FillNode(items, newNode);
            }
        }
    }