C# 从 DataTable 填充 TreeView

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14003698/
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-10 10:21:18  来源:igfitidea点击:

Populate TreeView from DataTable

c#.netwinformsdatatabletreeview

提问by Azri Zakaria

I have created an account table in my database, with these columns:

我在我的数据库中创建了一个帐户表,其中包含以下列:

ID
Name
ParentID

This is an example of how records have been stored:

这是记录如何存储的示例:

ID   Name    ParentID
1    BANK A  0
2    0001    1
3    0002    1
4    BANK B  0
5    0001    4
6    0002    4

But the company name does not come from database, it comes from code. So how can I expand the TreeViewlike this?

但是公司名称不是来自数据库,而是来自代码。那么我怎样才能TreeView像这样扩展呢?

├─ BANK A
│  ├─ 0001
│  └─ 0002
└─ BANK B
   ├─ 0001
   └─ 0002

How can I do this in C#? I also tried from HEREbut I still don't understand it.

我怎样才能在 C# 中做到这一点?我也从这里尝试过,但我仍然不明白。

回答by Sebastien H.

i have found a piece of code that worked great for me after spending 2h to make complicated algorithlms :

在花了 2 小时制作复杂的算法后,我发现了一段对我有用的代码:

 //In Page load
 //select where id is null to retrieve the parent nodes 
 //in a datatable (called table here)
 foreach (DataRow row in table.Rows)
 {
   TreeNode node = new TreeNode();
   node.Text = row["title"].ToString();
   node.Value = row["id"].ToString();
   //you can affect the node.NavigateUrl

   node.PopulateOnDemand = true;
   TreeView1.Nodes.Add(node);
 }

then create the TreeNodePopulate event :

然后创建 TreeNodePopulate 事件:

 protected void TreeView1_TreeNodePopulate(Object sender, TreeNodeEventArgs e)
 {
     string id= e.Node.Value;
     //do your "select from yourTable where parentId =" + id;

     foreach (DataRow row in table.Rows)
     {
         TreeNode node = new TreeNode(row["title"], row["id"])
         node.PopulateOnDemand = true;    
         e.Node.ChildNodes.Add(node);
     }

 }

it worked like hell for me, i hope it will help !

它对我来说就像地狱一样,我希望它会有所帮助!

回答by Reza Aghaei

To populate a TreeViewfrom a DataTableor any IEnumerable<T>, you should be able to answer the following questions:

要从TreeViewaDataTable或 any填充 a IEnumerable<T>,您应该能够回答以下问题:

  1. What are data source items
  2. How to detect if an item in data source is a root item in tree
  3. How to find child items of an item in data source
  4. How to create tree item from data source item.
  1. 什么是数据源项
  2. 如何检测数据源中的项目是否是树中的根项目
  3. 如何在数据源中查找项目的子项目
  4. 如何从数据源项创建树项。

By passing answer of above questions as lambda expressions to the following method, it uses a recursive algorithm to create a list of TreeNodewhich you can add to TreeView. Each TreeNodecontains the descendant TreeNodeitems:

通过将上述问题的答案作为 lambda 表达式传递给以下方法,它使用递归算法创建一个列表TreeNode,您可以将其添加到TreeView. 每个都TreeNode包含后代TreeNode项目:

private IEnumerable<TreeNode> GetTreeNodes<T>(
    IEnumerable<T> source,
    Func<T, Boolean> isRoot,
    Func<T, IEnumerable<T>, IEnumerable<T>> getChilds,
    Func<T, TreeNode> getItem)
{
    IEnumerable<T> roots = source.Where(x => isRoot(x));
    foreach (T root in roots)
        yield return ConvertEntityToTreeNode(root, source, getChilds, getItem); ;
}

private TreeNode ConvertEntityToTreeNode<T>(
    T entity,
    IEnumerable<T> source,
    Func<T, IEnumerable<T>, IEnumerable<T>> getChilds,
    Func<T, TreeNode> getItem)
{
    TreeNode node = getItem(entity);
    var childs = getChilds(entity, source);
    foreach (T child in childs)
        node.Nodes.Add(ConvertEntityToTreeNode(child, source, getChilds, getItem));
    return node;
}

Example

例子

I assume you have loaded data into the following structure:

我假设您已将数据加载到以下结构中:

var dt = new DataTable();
dt.Columns.Add("Id", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("ParentId", typeof(int));

dt.Rows.Add(1, "Menu 1", DBNull.Value);
dt.Rows.Add(11, "Menu 1-1", 1);
dt.Rows.Add(111, "Menu 1-1-1", 11);
dt.Rows.Add(112, "Menu 1-1-2", 11);
dt.Rows.Add(12, "Menu 1-2", 1);
dt.Rows.Add(121, "Menu 1-2-1", 12);
dt.Rows.Add(122, "Menu 1-2-2", 12);
dt.Rows.Add(123, "Menu 1-2-3", 12);
dt.Rows.Add(124, "Menu 1-2-4", 12);
dt.Rows.Add(2, "Menu 2", DBNull.Value);
dt.Rows.Add(21, "Menu 2-1", 2);
dt.Rows.Add(211, "Menu 2-1-1", 21);

Then to convert it nodes of a TreeView, you can use the following code:

然后将其转换为 a 的节点TreeView,您可以使用以下代码:

var source = dt.AsEnumerable();
var nodes = GetTreeNodes(
        source,
        (r) => r.Field<int?>("ParentId") == null,
        (r, s) => s.Where(x => r["Id"].Equals(x["ParentId"])),
        (r) => new TreeNode { Text = r.Field<string>("Name") }
);
treeView1.Nodes.AddRange(nodes.ToArray());

As a result, you will have the following tree structure:

因此,您将拥有以下树结构:

├─ Menu 1
│  ├─ Menu 1-1
│  │  ├─ Menu 1-1-1
│  │  └─ Menu 1-1-2
│  └─ Menu 1-2
│     ├─ Menu 1-2-1
│     ├─ Menu 1-2-2
│     ├─ Menu 1-2-3
│     └─ Menu 1-2-4
└─ Menu 2
   └─ Menu 2-1
      └─ Menu 2-1-1