通常每个级别的菜单都需要一个与之关联的不同循环,例如第一级(例如:home、products、about_us)将水平显示在顶部,第二级将出现在相关父菜单项下方的下拉列表中,第三级将出现在第二级菜单项等下方。
因此,对于循环,您理论上不希望按级别拆分它们,同时保持与父菜单项的链接,以便显示它们。另一个更普遍的事情是树中的最高菜单通常被忽略为其他菜单项的容器元素,这允许您拥有多个顶级菜单,如下所示:
编辑: 修复了代码..随时返回编辑历史以了解我是多么的非天才:p
string html;
int lastLevel = 0;
void placeMenu( Menu menu, int level)
{
// if level hasn't changed close last menu-item
if( lastLevel == level ) html += "</li>";
// if we're deeper, open a new <UL>
else if( lastLevel < level ) html += "<ul>";
// if we're less deep, close the last <UL> and it's parent menu-item
else if( lastLevel > level ) html += "</ul></li>";
// add current menu item without closing it's <LI> so the next itteration of the loop can add a submenu if needed
html += "<li><a href='http://link/to/page'>" + menu.Name + "</a>";
lastLevel = level;
}
void setupMenu( Menu menu, int level )
{
foreach( var currentMenu in menu._ChildMenus )
{
// place current menu
placeMenu( currentMenu, level + 1 );
// place submenus
setupMenu( currentMenu, level + 1 );
}
}
string setupWholeMenu( Menu menu )
{
setupMenu( menu, 0 );
// close any elements left open by the recursive loop
html = html + "</li></ul>";
return html;
}
此代码旨在从您的菜单结构中创建一个普通的 html 无序级列表,这是在 HTML 中添加和设置菜单样式的标准方法,当您拥有这种格式的菜单时,请查看其中一些资源以设置菜单样式。在这里使用 HTML 无序列表的原因是,如果正确实施,如果禁用 Javascript 和 CSS(GSM 和屏幕阅读器适用于部分视力),这个列表结构仍然会显示,并且如果禁用 Javascript,它仍然适用于 IE6+ 的所有内容。
老实说,虽然在 MVC 中通常更容易以声明方式直接将菜单设置为 HTML 中的无序列表,然后如果将其放置在部分共享页面中或通过定义在任何地方显示它,则可以以多种方式设置它的样式它在您的布局页面中。如果您具有如上所示的动态菜单结构,这种方法仍然可以工作,只是您使用 Razor 构建列表,这可能也更容易。
另一点需要注意的是,在这种递归函数中,您应该使用StringBuilder,因为它比连接字符串更有效。然而,对于一个菜单结构(最多包含 30 个项目,每个项目由 2-3 个 concats 构建),这不会导致任何明显的延迟,只是将来要记住的事情。