在Web开发中,无限级的分类的应用很多,我们能够用各种方法来实现无限级分类。比如,jQuery中的treeTable Plugin可以实现无限级分类,当然,jQuery总归是客户端的,还需要服务端配合生成Table。在ASP.NET 中有SiteMap,可以实现生成无限级分类。即使是在ASP.NET MVC中,也有开源的ASP.NET MVC SiteMap Provider。
然而,jQuery中的treeTable是以生成表格的形式生成,没有办法处理li格式;ASP.NET 原有的SiteMap在MVC中表现不佳,毕竟机制上存在出入;开源的ASP.NET MVC SiteMap Provider倒是一个选择,只是,个人看到繁杂的配置,顿时失去了耐心。因此,自己在HtmlHelper上进行了扩展,使得在视图中也可以正常使用无限级分类,具体代码如下:
public interface IMutilevelMenuable
{
int Id {get;}
string Name { get; }
string AliasName { get; }
int Parent { get; }
}
首先定义一个接口,当然,如果你是一个类,那也就不是必须的了。
public static class MutiLevelMenuHelper
{
/// <summary>
/// 生成无限级的分类列表
/// </summary>
/// <param name="helper">HtmlHelper扩展方法对象</param>
/// <param name="menus">所有的对象</param>
/// <param name="menuId">要查找子分类的父分类ID</param>
/// <param name="currentId">当前页面的分类ID</param>
/// <param name="currentMenuUrlParameter">在URL中使用的分类ID的参数名称</param>
/// <returns>返回无限级分类的HTML</returns>
public static MvcHtmlString MutiLevelMenu<T>(this HtmlHelper helper, IEnumerable<T> menus, int menuId, int currentId, string currentMenuUrlParameter) where T : IMutilevelMenuable
{
IEnumerable<T> innerMenus = menus.Where(i => i.Parent == menuId);
if (innerMenus.Count() == 0) return MvcHtmlString.Create("");
System.Web.Routing.RouteData rd = helper.ViewContext.RouteData;
string controller = rd.GetRequiredString("controller");
string action = rd.GetRequiredString("action");
System.Web.Routing.RouteValueDictionary values =rd.Values;
if(!values.ContainsKey(currentMenuUrlParameter))
values[currentMenuUrlParameter] = currentId;
#region Code by Mitchell @2012-06-08
StringBuilder menuHtml = innerMenus.Aggregate(new StringBuilder().AppendFormat("<ul class=\"node-for-node{0}\">\r\n", menuId), (seed, menu) =>
{
values[currentMenuUrlParameter] = menu.Id;
if (menu.Id == currentId)
{
seed
.AppendFormat("<li id=\"node{0}\">\r\n", menu.Id)
.AppendFormat("<h3>{0}</h3>", menu.Name)
.Append(MutiLevelMenu(helper, menus, menu.Id, currentId, currentMenuUrlParameter))
.Append("</li>\r\n");
}
else
{
seed
.AppendFormat("<li id=\"node{0}\">\r\n", menu.Id)
.Append(helper.ActionLink(menu.Name, action, controller, values, new Dictionary<string, object> { { "class", "menu-link" } }).ToHtmlString())
.Append(MutiLevelMenu(helper, menus, menu.Id, currentId, currentMenuUrlParameter))
.Append("</li>\r\n");
}
return seed;
});
menuHtml.Append("</ul>");
#endregion
return MvcHtmlString.Create(menuHtml.ToString());
}
}
}
之后定义一个HtmlHelper的泛型方法,改方法参数T必须实现了前面定义的接口,这样在方法体内就可以实现调用。
至于方法体里面,就是个递归,没有什么稀奇的东西。
由于是扩展方法,所以必须引用:
using System.Web.Mvc;
using System.Web.Mvc.Html;
之后,在视图中使用@using 引用本扩展方法即可。
在需要产生无限级分类的地方使用下面代码:
@Html.MutiLevelMenu(Model.AllCategories, 0, 1, "Id")
参数的说明见方法定义。
这样就可以了。
至于样式,根据个人喜好定义即可。