asp.net databound menu multiniveau

J’utilise actuellement un contrôle de menu asp.net pour charger des éléments parent / enfant d’une table. Le problème que j’ai est que si l’enfant a un autre enfant. Mon code est un peu statique dans ce sens et je n’arrive pas à trouver un meilleur ou “le” moyen de le faire. J’ai vu le plan du site comme source de données, mais je n’ai pas besoin de plan du site et je pense que ce serait trop cher pour ce que j’ai à accomplir.

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

comme vous pouvez le voir, cela fonctionne mais pour 2 niveaux 🙁 et bien sûr, je pourrais mettre un autre enfant à l’intérieur de l’enfant pour créer le 3ème niveau, mais que se passera-t-il s’il y a un 4ème, 5ème? treeview a sur la population mais apparemment le menu ne le fait pas. Merci d’avance.

Voici une façon de le faire.

  • Représenter la relation parent / enfant dans votre table avec une liste d’adjacence
  • Mapper cette liste de contiguïté dans une arborescence
  • Convertissez cette arborescence en votre structure d’éléments de menu

Vous pourriez peut-être ignorer cette étape intermédiaire et mapper la liste de contiguïté directement sur une arborescence de MenuItems, peut-être avec certaines méthodes d’extension sur MenuItem.

Mais peu importe…

Default.aspx

 <%@ Page Language="C#" Inherits="MenuTreeDemo.Default" %>    Default   

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(ssortingng)); table.Columns.Add("Url", typeof(ssortingng)); 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 eg 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(); map[0] = new MenuNode() { Id = 0 }; // root node foreach (DataRow row in table.Rows) { int nodeId = int.Parse(row["Id"].ToSsortingng()); int parentId = int.Parse(row["ParentId"].ToSsortingng()); 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"].ToSsortingng()); int parentId = int.Parse(row["ParentId"].ToSsortingng()); ssortingng description = row["Description"].ToSsortingng(); ssortingng url = row["Url"].ToSsortingng(); 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 ssortingng Description { get; set; } public ssortingng Url { get; set; } public List Children { get; set; } public MenuNode () { Children = new List(); } // 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; } } }