递归填充树视图(复杂的情况)

-2 c# asp.net treeview

我有一些严重的问题,递归填充树视图,我会给你任何帮助.

我有这个DataTable:

ItemID ItemDesc  Project  Room  Closet  

Item1  Item1Desc Project1 RoomE Closet-7  
Item2  Item2Desc Project1 RoomW Closet8  
Item3  Item3Desc Project1 RoomW Closet8  
Item4  Item4Desc Project1 RoomN Closet2  
Item5  Item5Desc Project1 RoomN Closet9  
Item6  Item6Desc Project2 RoomN Closet2  
Item7  Item7Desc Project2 RoomW Closet9  

我想创建一个这样的TreeView:

  • PROJECT1
    • Roome来
      • Closet7
        • Item1Desc
    • RoomW
      • Closet8
        • Item2Desc
        • Item3Desc
    • RoomN
      • Closet2
        • Item4Desc
      • Closet9
        • Item5Desc
  • 项目2
    • RoomN
      • Closet2
        • Item6Desc
    • RoomW
      • Closet2
        • Item7Desc

我试图数据树视图的方式是使用

private List<treeDataItem> treeData = new List<treeDataItem>();  
mytreeView.DataFieldID = "ID";  
mytreeView.DataFieldParentID = "ParentID";  
mytreeView.DataTextField = "Text";  
mytreeView.DataValueField = "Value";  
mytreeView.DataSource = treeData;  
mytreeView.DataBind();  
Run Code Online (Sandbox Code Playgroud)

我试图通过DataTable循环,所以我可以填充treeData但我无法正确输入ParentID.

而且,为了使事情变得复杂,DataTable中的字段数量是可变的.
这意味着我可以有更多字段来识别像"壁橱抽屉"这样的项目,然后可能是"壁橱抽屉部分"等.

所以DataTable有一次可以像:

ItemID     ItemDescription     Project     Room     Closet     Closet Drawer  

还有一次像:

ItemID     ItemDescription     Project     Room     Closet     Closet Drawer     Closet Drawer Section

基于用户选择.

这是treeDataItem类:

internal class treeDataItem
{
    public string Text { get; set; }
    public int ID { get; set; }
    public int ParentID { get; set; }
    public Guid Value { get; set; }

    public treeDataItem(int id, int parentId, string text, string value)
    {
        ID = id;
        ParentID = parentId;
        Text = text;
        Value = value;
    }
}
Run Code Online (Sandbox Code Playgroud)

dtb*_*dtb 6

我不熟悉ASP.NET树视图控件,所以这是一个通用的解决方案.

DateTable行

class Foo
{
    public string A { get; set; }
    public string B { get; set; }
    public string C { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

树节点

class Node
{
    private readonly string name;
    private readonly Node[] children;

    public Node(string name, Node[] children)
    {
        this.name = name;
        this.children = children;
    }
}
Run Code Online (Sandbox Code Playgroud)

递归算法将行分组到节点中

static IEnumerable<Node> Traverse<T, U>(
    IEnumerable<T> items,
    Func<T, U>[] keySelectors,
    int selectorIndex)
{
    if (selectorIndex < keySelectors.Length)
    {
        foreach (var g in items.GroupBy(keySelectors[selectorIndex]))
        {
            yield return new Node(g.Key.ToString(),
                Traverse(g, keySelectors, selectorIndex + 1).ToArray());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

测试

var items = new[]
               {
                   new Foo { A = "A1", B = "B1", C = "C1" },
                   new Foo { A = "A1", B = "B1", C = "C2" },
                   new Foo { A = "A1", B = "B2", C = "C1" },
                   new Foo { A = "A1", B = "B2", C = "C2" },
                   new Foo { A = "A2", B = "B1", C = "C1" },
                   new Foo { A = "A2", B = "B1", C = "C2" },
                   new Foo { A = "A2", B = "B2", C = "C1" },
                   new Foo { A = "A2", B = "B2", C = "C2" },
               };

var nodes = Traverse(items, new Func<Foo, string>[]
                            {
                                f => f.A,
                                f => f.B,
                                f => f.C
                            }, 0).ToArray();
Run Code Online (Sandbox Code Playgroud)

产量

  • A1
    • B1
      • C1
      • C2
    • B2
      • C1
      • C2
  • A2
    • B1
      • C1
      • C2
    • B2
      • C1
      • C2