2011-12-02 91 views
1

我目前使用asp.net菜單控件從表父/子項加載。我遇到的問題是,如果孩子有另一個孩子。我的代碼在這個意義上是靜態的,我似乎無法找到一個更好或「實現」的方式。我已經將站點地圖看作是數據源,但我不需要站點地圖,並且覺得這對我需要實現的東西來說只是矯枉過正。asp.net databound菜單多級

foreach (ClassName option in list) 
{ 
    MenuItem module = new MenuItem(option.Description.ToLower(), "", "", option.Url + "?option=" + option.Optionid); 
    module.Selectable = true; 
    navigation.Items.Add(module); 
    //this is my second level 
    foreach (ClassName child in listfromparent(option.Optionid)) 
    { 
     MenuItem childmenu = new MenuItem(child.Description.ToLower(), "", "", child.Url + "?option=" + child.Optionid); 
     module.ChildItems.Add(childmenu); 
    } 
} 

,你可以看到這個工作,但對於2級:( 當然我可以把另一個childlevel內孩子創造3級但如果有一個第四,第五?所以這就是爲什麼我需要它做它自己。我注意到樹狀具有onpopulate但顯然菜單沒有。在此先感謝。

回答

2

這裏有一種方法,你可以做到這一點。

  • 代表的父/子在你的表的關係鄰接名單
  • 是鄰接表映射成一個樹狀結構
  • 轉換是樹形結構到你的菜單項結構

也許你可以跳過中間步驟和鄰接表與一些地圖直的MenuItems的一棵樹,也許MenuItem上的擴展方法。

但無論如何...

Default.aspx的

<%@ Page Language="C#" Inherits="MenuTreeDemo.Default" %> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html> 
<head runat="server"> 
    <title>Default</title> 
</head> 
<body> 
    <form id="form1" runat="server"> 
     <asp:Menu ID="MyMenu" runat="server" StaticDisplayLevels="3" /> 
    </form> 
</body> 
</html> 

Default.aspx.cs

using System; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 
using System.Data; 
using System.Collections.Generic; 

namespace MenuTreeDemo 
{ 
    public partial class Default : System.Web.UI.Page 
    { 
     protected void Page_Load(object sender, EventArgs e)  
     { 
      if (!IsPostBack) 
      { 
       MenuNode root = ConvertTableToTree(GetTreeTable()); 
       foreach (MenuNode topLevelNode in root.Children) 
       { 
        MyMenu.Items.Add(topLevelNode.ToMenuItem()); // Visits all nodes in the tree. 
       } 
      } 
     } 


     // The menu tree as an adjacency list in a table. 
     static DataTable GetTreeTable() 
     { 
      DataTable table = new DataTable(); 
      table.Columns.Add("Id", typeof(int)); 
      table.Columns.Add("Description", typeof(string)); 
      table.Columns.Add("Url", typeof(string)); 
      table.Columns.Add("ParentId", typeof(int)); 

      table.Rows.Add(1, "TopMenu1", "/foo.html", 0); 
      table.Rows.Add(2, "SubMenu1.1", "/baz.html", 1); 
      table.Rows.Add(3, "SubMenu1.2", "/barry.html", 1); 
      table.Rows.Add(4, "SubMenu1.2.1", "/skeet.html", 3); 
      table.Rows.Add(5, "TopMenu2", "/bar.html", 0); 
      table.Rows.Add(6, "TopMenu3", "/bar.html", 0); 
      table.Rows.Add(7, "SubMenu3.1", "/ack.html", 6); 

      return table; 
     } 


     // See e.g. http://stackoverflow.com/questions/2654627/most-efficient-way-of-creating-tree-from-adjacency-list 
     // Assuming table is ordered. 
     static MenuNode ConvertTableToTree(DataTable table) 
     { 
      var map = new Dictionary<int, MenuNode>(); 
      map[0] = new MenuNode() { Id = 0 }; // root node 

      foreach (DataRow row in table.Rows) 
      { 
       int nodeId = int.Parse(row["Id"].ToString()); 
       int parentId = int.Parse(row["ParentId"].ToString()); 

       MenuNode newNode = MenuNodeFromDataRow(row); 

       map[parentId].Children.Add(newNode); 
       map[nodeId] = newNode; 
      } 

      return map[0]; // root node 
     } 


     static MenuNode MenuNodeFromDataRow(DataRow row) 
     { 
      int nodeId = int.Parse(row["Id"].ToString()); 
      int parentId = int.Parse(row["ParentId"].ToString()); 
      string description = row["Description"].ToString(); 
      string url = row["Url"].ToString(); 

      return new MenuNode() { Id=nodeId, ParentId=parentId, Description=description, Url=url }; 
     } 
    } 
} 

MenuNode.cs

using System; 
using System.Collections.Generic; 
using System.Web.UI.WebControls; 

namespace MenuTreeDemo 
{ 
    public class MenuNode 
    { 
     public int Id { get; set; } 
     public int ParentId { get; set; } 
     public string Description { get; set; } 
     public string Url { get; set; } 
     public List<MenuNode> Children { get; set; } 


     public MenuNode() 
     { 
      Children = new List<MenuNode>(); 
     } 


     // Will visit all descendants and turn them into menu items. 
     public MenuItem ToMenuItem() 
     { 
      MenuItem item = new MenuItem(Description) { NavigateUrl=Url }; 
      foreach (MenuNode child in Children) 
      { 
       item.ChildItems.Add(child.ToMenuItem()); 
      } 

      return item; 
     } 
    } 
} 
+0

謝謝!這很好,我只是修改它與我目前的類而不是datatable工作。抱歉,我花了很長時間,但有點長的週末,所以我今天就試了:) – Andres

+0

嗨小幫助我需要這樣的一些事情相同代碼http://www.snoupix.com/demo/css3-mega-dropdown-menu/demo.html是否可能 – Dotnet