2011-06-12 16 views
54

當我想要一個特定的菜單鏈接是活躍在給定的頁面,我用剃刀在這種方法:更好的辦法讓MVC 3剃鬚刀活動頁面鏈接

在主佈局我有這些檢查:

var active = ViewBag.Active; 
const string ACTIVE_CLASS = "current"; 

if (active == "home") 
{ 
    ViewBag.ActiveHome = ACTIVE_CLASS; 
} 
if (active == "products") 
{ 
    ViewBag.ActiveProducts = ACTIVE_CLASS; 
} 

在主佈局HTML菜單:

<ul> 
<li class="@ViewBag.ActiveHome"><a href="/">Home</a></li> 
<li class="@ViewBag.ActiveProducts"><a href="@Url.Action("index", "products")">Products</a></li> 
</ul> 

在s pecifying到在不同的視圖中使用該佈局頁:

@{ 
    ViewBag.Active = "home"; 
    Layout = "~/Views/Shared/_Layout.cshtml"; 
} 

是否有更好的方法來sepcify活動鏈接,比我目前使用的呢?

回答

126

一個更好的辦法是使用HTML幫助:

using System.Web.Mvc; 
using System.Web.Mvc.Html; 

public static class MenuExtensions 
{ 
    public static MvcHtmlString MenuItem(
     this HtmlHelper htmlHelper, 
     string text, 
     string action, 
     string controller 
    ) 
    { 
     var li = new TagBuilder("li"); 
     var routeData = htmlHelper.ViewContext.RouteData; 
     var currentAction = routeData.GetRequiredString("action"); 
     var currentController = routeData.GetRequiredString("controller"); 
     if (string.Equals(currentAction, action, StringComparison.OrdinalIgnoreCase) && 
      string.Equals(currentController, controller, StringComparison.OrdinalIgnoreCase)) 
     { 
      li.AddCssClass("active"); 
     } 
     li.InnerHtml = htmlHelper.ActionLink(text, action, controller).ToHtmlString(); 
     return MvcHtmlString.Create(li.ToString()); 
    } 
} 

然後:

<ul> 
    @Html.MenuItem("Home", "Home", "Home") 
    @Html.MenuItem("Products", "Index", "Products") 
</ul> 

爲了讓你需要你的意見來識別您的擴展上面的工作:在Web.config文件在Views文件夾中,在名稱空間標記內添加<add namespace="yourNamespacehere.Helpers" />。然後構建您的項目並關閉並重新打開您要添加的視圖。

然後基於當前動作和控制器,助手將在生成錨時添加或不添加active類。

+0

看起來像那些MVC HTML幫手是一個好主意,我可能會更多地考慮這一點。謝謝,像魅力一樣工作。 – Jens 2011-06-12 16:34:52

+0

不錯!我想這樣做,但無法弄清楚如何解決在HTML幫助器中的活動控制器和動作。 – 2011-06-28 20:58:55

+0

這完美的作品!謝謝Darin! – 2012-04-09 15:08:49

2

如果您想在文本中包含HTML格式,請使用此InnerHtml;

li.InnerHtml = "<a href=\"" + new UrlHelper(htmlHelper.ViewContext.RequestContext).Action(action, controller).ToString() + "\">" + text + "</a>"; 

文字可能是 「<b>大膽</B >正常」;

6

在Darin的示例中進行了擴展,下面是爲輔助程序的RouteValues和HtmlAttributes添加其他可選參數的完整類。實際上,它的行爲就像基本的ActionLink一樣。

using System; 
using System.Web.Mvc; 
using System.Web.Mvc.Html; 

namespace MYNAMESPACE.Helpers { 
    public static class MenuExtensions { 
     public static MvcHtmlString MenuItem(this HtmlHelper htmlHelper, 
              string text, string action, 
              string controller, 
              object routeValues = null, 
              object htmlAttributes = null) { 
      var li = new TagBuilder("li"); 
      var routeData = htmlHelper.ViewContext.RouteData; 
      var currentAction = routeData.GetRequiredString("action"); 
      var currentController = routeData.GetRequiredString("controller"); 
      if (string.Equals(currentAction, 
           action, 
           StringComparison.OrdinalIgnoreCase) && 
       string.Equals(currentController, 
           controller, 
           StringComparison.OrdinalIgnoreCase)) { 
       li.AddCssClass("active"); 
      } 
      if (routeValues != null) { 
       li.InnerHtml = (htmlAttributes != null) 
        ? htmlHelper.ActionLink(text, 
              action, 
              controller, 
              routeValues, 
              htmlAttributes).ToHtmlString() 
        : htmlHelper.ActionLink(text, 
              action, 
              controller, 
              routeValues).ToHtmlString(); 
      } 
      else { 
       li.InnerHtml = htmlHelper.ActionLink(text, 
                action, 
                controller).ToHtmlString(); 
      } 
      return MvcHtmlString.Create(li.ToString()); 
     } 
    } 
} 

並在視圖文件夾中的web.config:

<system.web.webPages.razor> 
    <host ... /> 
    <pages ... > 
    <namespaces> 
     ... 

     ... 
     <add namespace="MYNAMESPACE.Helpers" /> 
    </namespaces> 
    </pages> 
</system.web.webPages.razor> 
0

此代碼爲我工作很好,即使是在新的Visual Studio 2013 MVC5 /引導項目。還要注意你可以改變li.AddCssClass(「active」);如果您想單獨保留Bootstrap「活動」類,則可以指向自定義類。我在項目的Site.css文件中添加了一個名爲「activemenu」的文件,並且做了我想要的任何特定導航欄樣式更改。

在上面剛剛被更改了該代碼行把一切工作:

li.AddCssClass("activemenu"); 

在我的site.css添加一個簡單的類我的目的:

.activemenu { 
    text-decoration: underline; 
} 

另外,您可以改變背景顏色和/或邊界等...

2

更新了RC2 - 對於那些想知道如何在MVC6/Asp.Net 5中做到這一點 - 相似但略有不同。現在沒有MvcHtmlString,和RouteData完全不同。此外,上下文對象現在應該是IHtmlContent而不是HtmlHelper

using System; 
using Microsoft.AspNet.Mvc.Rendering; 

public static class MenuExtensions 
{ 
    public static IHtmlContent MenuItem(
     this IHtmlHelper htmlHelper, 
     string text, 
     string action, 
     string controller 
    ) 
    { 

     var li = new TagBuilder("li") { TagRenderMode = TagRenderMode.Normal }; 
     var routeData = htmlHelper.ViewContext.RouteData; 
     var currentAction = routeData.Values["action"].ToString(); 
     var currentController = routeData.Values["controller"].ToString(); 

     if (string.Equals(currentAction, action, StringComparison.OrdinalIgnoreCase) && 
      string.Equals(currentController, controller, StringComparison.OrdinalIgnoreCase)) 
     { 
      li.AddCssClass("active"); 
     } 


     li.InnerHtml.AppendHtml(htmlHelper.ActionLink(text, action, controller)); 

     return li; 


    } 
} 
0

這裏是Darin的類的一個推廣在鏈接文字中插入HTML,而不是一個簡單的文本

using System; 
using System.Web.Mvc; 
using System.Web.Mvc.Html; 

namespace YourNameSpaceHere 
{ 
    public static class MenuExtensions 
    { 
     public static MvcHtmlString MenuItem(
      this HtmlHelper htmlHelper, 
      string html, 
      string action, 
      string controller 
     ) 
     { 
      var li = new TagBuilder("li"); 
      var routeData = htmlHelper.ViewContext.RouteData; 
      var currentAction = routeData.GetRequiredString("action"); 
      var currentController = routeData.GetRequiredString("controller"); 
      if (string.Equals(currentAction, action, StringComparison.OrdinalIgnoreCase) && 
       string.Equals(currentController, controller, StringComparison.OrdinalIgnoreCase)) 
      { 
       li.AddCssClass("active"); 
      } 
      //generate a unique id for the holder and convert it to string 
      string holder = Guid.NewGuid().ToString(); 
      string anchor = htmlHelper.ActionLink(holder, action, controller).ToHtmlString(); 
      //replace the holder string with the html 
      li.InnerHtml = anchor.Replace(holder, html); 
      return MvcHtmlString.Create(li.ToString()); 
     } 
    } 
} 

,並使用它像這樣:

<ul> 
    @Html.MenuItem("<span class'ClassName'>Home</span>", "Home", "Home") 
</ul>