2010-04-03 19 views
11

Ho un oggetto di tipo elenco da cui desidero utilizzare per popolare una vista ad albero in asp.net C#.TreeView ricorsivo in ASP.NET

Ogni elemento oggetto ha:

id | Name | ParentId 

così per esempio:

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

Nell'esempio precedente, il genitore sarebbe Alice avere due figli Bob e Charlie. David è il figlio di Bob.

Ho avuto molti problemi cercando di compilare dinamicamente la vista ad albero in modo ricorsivo in C# ASP.NET

Se uno ha una soluzione semplice?

Btw: è possibile utilizzare People.Id, People.Name e People.ParentId per accedere ai membri poiché si tratta di un oggetto appartenente all'elenco.

Posso postare il mio codice finora (molti tentativi fatti) ma non sono sicuro di quanto sarà utile.

risposta

26

Penso che questo dovrebbe iniziare. Ho creato una classe MyObject per simulare il tuo oggetto.

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

Ecco un metodo per aggiungere nuovamente i nodi di visualizzazione ad albero in base all'elenco.

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: Questa è la soluzione che cercavo .. funziona perfettamente .. Grazie !! – waqasahmed

+0

In effetti, questa roba funziona perfettamente! Proprio quello che stavo cercando :) –

+0

L'elenco IEnumerable non verrà creato in memoria ad ogni iterazione? –

-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

Questo è un campione con Categoria entità che si fa riferimento. In primo luogo dobbiamo preparare la nostra fonte dati:

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

Poi, nel nostro codice dietro abbiamo:

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