2010-04-03 16 views
11

Tengo un objeto de la lista de tipos desde el que deseo utilizar para rellenar una vista de árbol en asp.net C#.TreeView recursivo en ASP.NET

Cada elemento objeto tiene:

id | Name | ParentId 

así por ejemplo:

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

En el ejemplo anterior, el padre sería Alice tener dos hijos Bob y Charlie. David es el hijo de Bob.

he tenido muchos problemas al tratar de rellenar dinámicamente la vista de árbol de forma recursiva en C# ASP.NET

¿Alguien tiene una solución sencilla?

Por cierto: puede utilizar People.Id, People.Name y People.ParentId para acceder a los miembros ya que es un objeto que pertenece a la lista.

Puedo publicar mi código hasta el momento (se han realizado muchos intentos) pero no estoy seguro de lo útil que será.

Respuesta

26

Creo que esto debería comenzar. Creé una clase MyObject para imitar tu objeto.

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

Aquí es un método para añadir recursivley vista de árbol nodos basados ​​en la lista.

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: Esta es la solución que estaba buscando .. funciona perfectamente .. Gracias !! – waqasahmed

+0

De hecho, ¡esto funciona a la perfección! Justo lo que estaba buscando :) –

+0

¿No se creará en la memoria la lista IEnumerable en cada iteración? –

-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

Esta es una muestra con entidad de categoría que hace referencia a sí mismo. En primer lugar debemos preparar nuestra fuente de datos:

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(); 
     } 

Luego, en nuestro código detrás tenemos:

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())); 
         } 
        } 
       } 
      } 
     }