2010-04-03 2 views
11

У меня есть объект списка типов, из которого я хочу использовать, чтобы заполнить дерево в asp.net C#.Рекурсивное TreeView в ASP.NET

Каждый элемент объекта имеет:

id | Name | ParentId 

так, например:

id | Name  | ParentId 
------------------------- 
1 | Alice | 0 
2 | Bob  | 1 
3 | Charlie | 1 
4 | David | 2 

В приведенном выше примере, родитель будет Алиса имея двух детей Боба и Чарли. Дэвид - ребенок Боба.

У меня было много проблем, пытающихся динамически заполнить TreeView рекурсивно в C# ASP.NET

Есть ли одна есть простое решение?

КПП: вы можете использовать People.Id, People.Name и People.ParentId для доступа к членам, так как это объект, принадлежащий списку.

Я могу опубликовать у вас мой код до сих пор (сделано много попыток), но не уверен, насколько он будет полезен.

ответ

26

Я думаю, это должно вас начать. Я создал класс MyObject для имитации вашего объекта.

public class MyObject 
{ 
    public int Id; 
    public int ParentId; 
    public string Name; 
} 

Ниже приведен метод рекурсивного добавления узлов дерева представлений на основе списка.

protected void Page_Load(object sender, EventArgs e) 
{ 
    if (!IsPostBack) 
    { 
     List<MyObject> list = new List<MyObject>(); 
     list.Add(new MyObject(){Id=1, Name="Alice", ParentId=0}); 
     list.Add(new MyObject(){Id=2, Name="Bob", ParentId=1}); 
     list.Add(new MyObject(){Id=3, Name="Charlie", ParentId=1}); 
     list.Add(new MyObject(){Id=4, Name="David", ParentId=2});    

     BindTree(list, null);    
    } 
} 

private void BindTree(IEnumerable<MyObject> list, TreeNode parentNode) 
{ 
    var nodes = list.Where(x => parentNode == null ? x.ParentId == 0 : x.ParentId == int.Parse(parentNode.Value)); 
    foreach (var node in nodes) 
    { 
     TreeNode newNode = new TreeNode(node.Name, node.Id.ToString()); 
     if (parentNode == null) 
     { 
      treeView1.Nodes.Add(newNode); 
     } 
     else 
     { 
      parentNode.ChildNodes.Add(newNode); 
     } 
     BindTree(list, newNode); 
    } 
} 
+1

+1: Это решение, которое я искал .. отлично работает .. спасибо !! – waqasahmed

+0

Действительно, этот материал отлично работает! Только то, что я искал :) – 2011-05-21 17:44:29

+0

Не будет ли список IEnumerable в памяти на каждой итерации? –

-1
//In load for example 
    if (!IsPostBack) 
    { 
      DataSet ds = new DataSet(); 
      ds = getRoles(); //function that gets data collection from db. 

      tvRoles.Nodes.Clear(); 

      BindTree(ds, null); 
      tvRoles.DataBind(); 

    }  

    private void BindTree(DataSet ds, TreeNode parentNode) 
    { 
     DataRow[] ChildRows; 
     if (parentNode == null) 
     { 
      string strExpr = "ParentId=0"; 
      ChildRows = ds.Tables[0].Select(strExpr);      
     } 
     else 
     { 
      string strExpr = "ParentId=" + parentNode.Value.ToString(); 
      ChildRows = ds.Tables[0].Select(strExpr); 
     } 
     foreach (DataRow dr in ChildRows) 
     { 
      TreeNode newNode = new TreeNode(dr["Name"].ToString(), dr["Id"].ToString()); 
      if (parentNode == null) 
      { 
       tvRoles.Nodes.Add(newNode); 
      } 
      else 
      { 
       parentNode.ChildNodes.Add(newNode); 
      } 
      BindTree(ds, newNode); 
     } 
    } 
0

Это пример с категорией объекта, который ссылается на себя. Во-первых, мы должны подготовить наш источник данных:

public class Category 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
     public int? ParentId { get; set; } 
     public virtual Category Parent { get; set; } 
     public virtual ICollection<Category> Children { get; set; } 
     public byte[] Image { get; set; } 
    } 

public class Product 
    { 
     public int Id { get; set; } 
     public string Code { get; set; } 
     public string Name { get; set; } 
     public Category ProductCategory { get; set; } 
     public int ProductCategoryId { get; set; } 
     public byte[] Image { get; set; } 
    } 

public List<Category> GethierarchicalTree(int? parentId=null) 
     { 
      var allCats = new BaseRepository<Category>().GetAll(); 

      return allCats.Where(c => c.ParentId == parentId) 
          .Select(c => new Category() 
          { 
           Id = c.Id, 
           Name = c.Name, 
           ParentId = c.ParentId, 
           Children = GetChildren(allCats.ToList(), c.Id) 
          }) 
          .ToList(); 
     } 

     public List<Category> GetChildren(List<Category> cats, int parentId) 
     { 
      return cats.Where(c => c.ParentId == parentId) 
        .Select(c => new Category 
        { 
         Id = c.Id, 
         Name = c.Name, 
         ParentId = c.ParentId, 
         Children = GetChildren(cats, c.Id) 
        }) 
        .ToList(); 
     } 

Затем в коде позади мы имеем:

protected void Page_Load(object sender, EventArgs e) 
     { 
      var hierarchicalData = new CategoryRepository().GethierarchicalTree(); 
      tv1.Nodes.Clear(); 
      var root = new TreeNode("0","Root"); 
      tv1.Nodes.Add(root); 
      BindTreeRecursive(hierarchicalData, root); 
     } 

     private void BindTreeRecursive(List<Category> hierarchicalData, TreeNode node) 
     { 
      foreach (Category category in hierarchicalData) 
      { 
       if (category.Children.Any()) 
       { 
        var n = new TreeNode(category.Name, category.Id.ToString()); 
        node.ChildNodes.Add(n); 
        BindTreeRecursive(category.Children.ToList(), n); 
       } 
       else 
       { 
        var n = new TreeNode(category.Name, category.Id.ToString()); 
        node.ChildNodes.Add(n); 

        if (new ProductRepository().Get(a => a.ProductCategoryId == category.Id).Any()) 
        { 
         var catRelatedProducts = new ProductRepository().Get(a => a.ProductCategoryId == category.Id).ToList(); 

         foreach (Product product in catRelatedProducts) 
         { 
          n.ChildNodes.Add(new TreeNode(product.Name,product.Id.ToString())); 
         } 
        } 
       } 
      } 
     }