
網站開發一定遇過網頁上有很多選項,這些選項又要用程式去生出來,還要去判斷選項是不是當前頁面來給予不同的CSS,原本的開發方式寫起來會很繁瑣又笨,但是在MVC上卻變得相當精美。
上述的問題以英文簡單來說就是Active Navigation Bar,所以我就用這個來當範例。
Active Navigation Bar
原本的prototype長的這個樣子。

轉成MVC寫法會變成大概這個樣子。
<ul>
<li>@Html.ActionLink("Home", "Index", "Home")</li>
<li>@Html.ActionLink("FAQ", "FAQ", "Home")</li>
<li>@Html.ActionLink("Contact Us", "Contact", "Home")</li>
</ul>
東西看起來是好了,但是還要去另外判斷目前的頁面來改CSS實在是很麻煩的一件事,這時候就可以用HtmlHelper Extension來精美的處理掉這件事。
HtmlHelper Extension
我是另外寫了一個叫做ActiveNavigationBar的功能去專門處理Navigation Bar這件事,用TagBuilder跟ActionLink組出我要的東西,然後借用demo小鋪的ASP.NET MVC 如何判斷現在是哪一頁這個功能去判斷使否在那頁,再去增加<li>的class,所以語法如下。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;
using System.Web.Mvc;
using System.Web.Mvc.Html;
namespace TestMVC.Common
{
public static class Helpers
{
public static MvcHtmlString ActiveNavigationBar(this HtmlHelper helper, string linkText, string actionName, string controllerName)
{
if (IsCurrentAction(helper, actionName, controllerName))
{
return ListLink(helper, linkText, actionName, controllerName, true);
}
return ListLink(helper, linkText, actionName, controllerName);
}
private static MvcHtmlString ListLink(this HtmlHelper helper, string linkText, string actionName, string controllerName, bool active)
{
var builder = new TagBuilder("li");
if(active) builder.AddCssClass("active");
builder.InnerHtml = helper.ActionLink(linkText, actionName, controllerName).ToHtmlString();
return new MvcHtmlString(builder.ToString());
}
private static MvcHtmlString ListLink(this HtmlHelper helper, string linkText, string actionName, string controllerName)
{
return ListLink(helper, linkText, actionName, controllerName, false);
}
//from domo
public static bool IsCurrentAction(this HtmlHelper helper, string actionName, string controllerName)
{
string currentControllerName = (string)helper.ViewContext.RouteData.Values["controller"];
string currentActionName = (string)helper.ViewContext.RouteData.Values["action"];
if (currentControllerName.Equals(controllerName, StringComparison.CurrentCultureIgnoreCase) &&
currentActionName.Equals(actionName, StringComparison.CurrentCultureIgnoreCase))
return true;
return false;
}
}
}有點長,我懶得排版了,反正他就會自動判斷要不要加css上去,如果有特例的地方也可以自行加上,我貼上的是沒有特例的版本。另外我想應該是MVC4的安全性考量(not sure),現在的版本用string輸出HtmlHelper到頁面上,會變成HtmlEncode過的格式,一個解法是在頁面上多做一次處理,另外一個就是改後端輸出了,所以我是寫成輸出為MvcHtmlString,而不是一般大部分人在HtmlHelper Extension寫的輸出為String。
Front-end
於是在頁面上引用這個Extension之後
@using TestMVC.Common;就可以很精美的處理掉繁雜的Active Navigation Bar問題了。

收工!!

No comments:
Post a Comment