利用ASP.NET SiteMap生成与Bootstrap"兼容"菜单

Bootstrap是Twitter推出的一个开源的用于前端开发的工具包。它由Twitter的设计师Mark Otto和Jacob Thornton合作开发,是一个CSS/HTML框架。本文提供了一个解决方案利用ASP.NET SiteMap生成与Bootstrap“兼容”的菜单。具体的原理很简单,就是利用SiteMap读取预先定义的网站结构,按照Bootstrap的标准生成相应的HTML。[源代码从这里下载]

我们将基于菜单的呈现定义在HtmlHelper的扩展方法中。如下面的代码片断,扩展方法RenderBootstrapMenu具有一个缺省的参数siteMapProviderName ,表示读取SiteMap结构采用的SiteMapProvider的配置名称。在该方法中,我们通过指定的SiteMapProvider(如果没有指定,则采用默认配置的SiteMapProvider)得到代表整个SiteMap根节点的SiteMapNode对象,并将其子节点(以及子节点的子节点,…)转换成相应的HTML。

   1: public static class BootstrapMenuExtensions
   2: {        
   3:     public static MvcHtmlString RenderBootstrapMenu(this HtmlHelper helper, string siteMapProviderName = "")
   4:     {
   5:         SiteMapProvider siteMapProvider = !string.IsNullOrEmpty(siteMapProviderName) ?
   6:             SiteMap.Providers[siteMapProviderName] :
   7:             SiteMap.Provider ?? SiteMap.Providers.Cast<SiteMapProvider>().First();
   8:         return new MvcHtmlString( RenderMenu(siteMapProvider.RootNode.ChildNodes));
   9:     }
  10:  
  11:     private static string RenderMenu(SiteMapNodeCollection siteMapNodes)
  12:     {
  13:         TagBuilder ul = new TagBuilder("ul");
  14:         ul.AddCssClass("nav");
  15:         ul.AddCssClass("nav-pills");
  16:  
  17:         foreach (SiteMapNode node in siteMapNodes)
  18:         {
  19:             ul.InnerHtml += GetMenuItemHtml(node);
  20:         }
  21:         return ul.ToString();
  22:     }
  23:  
  24:     private static string GetMenuItemHtml(SiteMapNode siteMapNode)
  25:     {
  26:         TagBuilder li = new TagBuilder("li");
  27:         li.AddCssClass("dropdown");
  28:  
  29:         TagBuilder link = new TagBuilder("a");
  30:         link.Attributes.Add("href", siteMapNode.Url);
  31:         link.Attributes.Add("title", siteMapNode.Description);
  32:         link.SetInnerText(siteMapNode.Title);
  33:  
  34:         if (!siteMapNode.HasChildNodes)
  35:         {
  36:             li.InnerHtml += link.ToString();
  37:             return li.ToString();
  38:         }
  39:  
  40:         link.AddCssClass("dropdown-toggle");
  41:         link.Attributes.Add("data-toggle", "dropdown");
  42:         TagBuilder caret = new TagBuilder("b");
  43:         caret.AddCssClass("caret");
  44:         link.InnerHtml += caret.ToString();
  45:  
  46:         TagBuilder ul = new TagBuilder("ul");
  47:         ul.AddCssClass("dropdown-menu");
  48:         foreach (SiteMapNode node in siteMapNode.ChildNodes)
  49:         {
  50:             ul.InnerHtml += GetSubItemHtml(node);
  51:         }
  52:         li.InnerHtml += link.ToString();
  53:         li.InnerHtml += ul.ToString();
  54:         return li.ToString();
  55:     }
  56:  
  57:     private static string GetSubItemHtml(SiteMapNode siteMapNode)
  58:     {
  59:         TagBuilder li = new TagBuilder("li");
  60:  
  61:         TagBuilder link = new TagBuilder("a");
  62:         link.Attributes.Add("href", siteMapNode.Url);
  63:         link.Attributes.Add("title", siteMapNode.Description);
  64:         link.SetInnerText(siteMapNode.Title);
  65:         li.InnerHtml += link.ToString();
  66:  
  67:         if (siteMapNode.HasChildNodes)
  68:         {
  69:             link.AddCssClass("dropdown-toggle");
  70:             link.Attributes.Add("data-toggle", "dropdown");
  71:  
  72:             li.AddCssClass("dropdown-submenu");
  73:             TagBuilder ul = new TagBuilder("ul");
  74:             ul.AddCssClass("dropdown-menu");
  75:             foreach (SiteMapNode node in siteMapNode.ChildNodes)
  76:             {
  77:                 ul.InnerHtml += GetSubItemHtml(node);
  78:             }
  79:             li.InnerHtml += ul.ToString();
  80:         }
  81:         return li.ToString();
  82:     }
  83: }

假设我们采用XmlSiteMapProvider,SiteMap结构通过如下的XML来定义,整个结构具有三个层次。

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
   3:   <siteMapNode url="Root" title="Root"  description="">
   4:     <siteMapNode url="A1" title="A1"  description="1st Level 1" />
   5:     <siteMapNode url="A2" title="A2"  description="1st Level 2" />
   6:     <siteMapNode url="A3" title="A3"  description="1st Level 3">
   7:       <siteMapNode url="B1" title="B1"  description="2nd Level 1" />
   8:       <siteMapNode url="B2" title="B2"  description="2nd Level 2" />
   9:       <siteMapNode url="B3" title="B3"  description="2nd Level 3">
  10:         <siteMapNode url="C1" title="C1"  description="3rd Level 1" />
  11:         <siteMapNode url="C2" title="C2"  description="3rd Level 2" />
  12:         <siteMapNode url="C3" title="C3"  description="3rd Level 3" />
  13:       </siteMapNode>
  14:     </siteMapNode>
  15:   </siteMapNode>
  16: </siteMap>

在如下一个View中,我们调用扩展方法RenderBootstrapMenu将由上面这个XML定义的菜单节点呈现出来。

   1: <!DOCTYPE html>
   2: <html>
   3: <head>
   4:     <title>Bootstrap Menu</title>
   5:     <link href="bootstrap/css/bootstrap.min.css" rel="stylesheet" />    
   6: </head>
   7: <body>
   8:     <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
   9:     <script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>
  10:     <div>
  11:         @Html.RenderBootstrapMenu()
  12:     </div>
  13: </body>
  14: </html>

最终呈现的效果如下所示:

菜单对应的HTML为:

   1: <ul class="nav-pills nav">
   2:     <li class="dropdown"><a href="/A1" title="1st Level 1">A1</a></li>
   3:     <li class="dropdown"><a href="/A2" title="1st Level 2">A2</a></li>
   4:     <li class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="/A3" title="1st Level 3">A3<b class="caret"></b></a>
   5:         <ul class="dropdown-menu">
   6:             <li><a href="/B1" title="2nd Level 1">B1</a></li>
   7:             <li><a href="/B2" title="2nd Level 2">B2</a></li>
   8:             <li class="dropdown-submenu"><a href="/B3" title="2nd Level 3">B3</a>
   9:                   <ul class="dropdown-menu">
  10:                        <li><a href="/C1" title="3rd Level 1">C1</a></li>
  11:                        <li><a href="/C2" title="3rd Level 2">C2</a></li>
  12:                        <li><a href="/C3" title="3rd Level 3">C3</a></li>
  13:                   </ul>
  14:             </li>
  15:         </ul>
  16:     </li>
  17: </ul>

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏阿炬.NET

FineUIMvc表格数据库分页,使用CYQ.Data组件

4168
来自专栏技术博客

Win8中缩放视图(SemanticZoom控件)

    SemanticZoom控件可以让用户缩放具有相同内容的两个不同视图。其中有一个是主视图。另外一个视图可以让用户进行快速导航。例如,当用户查看地址簿时,...

691
来自专栏阿炬.NET

FineUIMvc表格数据库分页,使用CYQ.Data组件

1284
来自专栏小灰灰

cocos2dx-v3.5 2048 (二): GameTool的设计与实现

前言 ---- 前一篇博文讲述了项目的架构,从中也可以看出GameTool 的主要功能是显示并随时更新分数和最高分数,其中主要用到的是Label ? ...

1935
来自专栏kalifaの日々

动态规划真的可以为所欲为的(Leetcode 62/63)

看起来不错的运行效率 62题: 动态规划递推公式: 站在当前方块上可选择的路径数量 = 我正下方那个方块可选择的路径数量 + 我右侧那个方块可选择的路径数量; ...

3646
来自专栏技术总结

YYImage框架瞧一瞧

建议查看原文:https://www.jianshu.com/p/83edaeeb5851(不定时更新)

1393
来自专栏hightopo

原 基于HTML5 Canvas WebG

1213
来自专栏cs

python爬虫练手,爬取名言,实现英语词典

她们的Html为,通过beautiful库的html.parser解析,通过id,class选择器,提取我们需要的东西。

985
来自专栏腾讯NEXT学位

一看就晕的React事件机制

6968
来自专栏小灰灰

zxing二维码生成服务之深度定制

二维码生成服务之深度定制 之前写了一篇二维码服务定制的博文,现在则在之前的基础上,再进一步,花样的实现深度定制的需求,我们的目标是二维码上的一切都是可以由用户...

4896

扫码关注云+社区

领取腾讯云代金券