鉴于分层菜单基于父子类 [英] Hierarchical menu in view based on parent child class
问题描述
我有一个视图模型:
public class Page
{
public int Id { get; set; }
public Page Parent { get; set; }
public string Name { get; set; }
public string Title { get; set; }
}
我传递了模型视图,我需要基于模型来创建分层菜单:
I am passing that model to a view, and i need to create a hierarchical menu based on the model:
<ul>
<li>Page
<ul>
<li>Sub Page</li>
</ul>
</li>
通过在所有我无法弄清楚我怎么会做在针对这一递归循环不缺乏努力。
Through no lack of effort at all i am unable to figure out how i will be doing this recursive loop in the view.
我可以在我的控制器中的标记,但是这不是测试友好。
I can create the markup in my controller, but that's not test friendly.
任何想法?
推荐答案
有很多方法可以动态地显示生成的菜单,我会后我做这件事的方式,我有两个类菜单&安培;菜单项(Menu(菜单)仅仅是其中的MenuItems是实际>真实的链接列表的包装),然后我有一个NavigationViewModel包装的一切。
there are many ways to display dynamicly generated menus and i will post my way of doing it, I have two classes Menu & MenuItem (a Menu is just a wrapper for a list of MenuItems which are the actual >"real" links) and then i have a NavigationViewModel to wrap everything.
public class MenuItem
{
public int MenuID { get; set; }
public int ID { get; set; }
public String Label { get; set; }
public String Link { get; set; }
public Boolean Show { get; set; }
public MenuItem(int menuId, int id, string label, string link, Boolean show)
{
this.MenuID = menuId;
this.ID = id;
this.Label = label;
this.Link = link;
this.Show = show;
}
}
//
public class Menu
{
public int ID { get; set; }
public string Name { get; set; }
public List<MenuItem> MenuItems { get; set; }
public Menu(int id, string name)
{
this.ID = id;
this.Name = name;
this.MenuItems = new List<MenuItem>();
}
}
//这是NavigationModel该包装的一切。
// this is NavigationModel that wrap everything.
public class NavigationModel
{
public int currentMenuID { get; set; }
// used to determine the current displayed Menu to add
// the "current" class to it. (to be set in the controller)
public int currentMenuItemID { get; set; }
// used to determine the current displayed MenuItem to add
// the "current" class to it. (to be set in the controller)
public List<Menu> Menus { get; set; }
public NavigationModel()
{
this.Menus = new List<Menu>();
// Set Default Menu ( Menu 1 )
this.currentMenuID = 1;
// Set Default Menau Item ( None )
this.currentMenuItemID = 0;
}
}
//这是建立一个NavigationModel的方法的一个例子。
// This is an example of a method that builds a NavigationModel.
private static NavigationModel BuildNavigationMenu(User currentUser, string rootURL)
{
string loginURL = rootURL + "Account/LogOn";
// Main Menu
Menu MainMenu = new Menu(1, "Home");
MainMenu.MenuItems.Add(new MenuItem(1, 1, "Welcome", rootURL, true));
MainMenu.MenuItems.Add(new MenuItem(1, 2, "How It Works", rootURL + "Home/HowDoesItWork", true));
// Work Menu
Menu WorkMenu = new Menu(2, "Work");
WorkMenu.MenuItems.Add(new MenuItem(2, 1, "Profile", rootURL + "User/Profile/" + currentUser.ID , true));
WorkMenu.MenuItems.Add(new MenuItem(2, 2, "Customers", "#", true));
// Add Menus To Navigation Model
NavigationModel navigationMenu = new NavigationModel();
navigationMenu.Menus.Add(MainMenu);
navigationMenu.Menus.Add(HireMenu);
return navigationMenu;
}
//我有一个NavigationHelper即采用与以下两种方法输出的HTML照顾。
// I have a NavigationHelper that takes care of outputting the HTML with the following two methods.
请注意:(这是一个简化版本,在我的实现可以使用菜单和放大器的ID;将菜单项,找到正在显示当前菜单和当前CSS类添加到其
Note: (this is a simplified version as in my implementation i use the id of the Menu & the MenuItem to locate the current menu that is being displayed and add the "current" CSS class to it"
public static string DisplayMenu(this HtmlHelper helper, NavigationModel navigationMenu)
{
public static string DisplayMenu(this HtmlHelper helper, NavigationModel navigationMenu)
{
String result = "<ul id='main-nav'>\n";
foreach(Menu menu in navigationMenu.Menus)
{
result += "<li>\n";
result += string.Format("<a href='#'> {0} </a>\n",helper.AttributeEncode(menu.Name));
result += "<ul>\n";
foreach(MenuItem item in menu.MenuItems)
{
result += NavigationHelper.ConvertToItem(helper, item);
}
result += "</ul>\n";
result += "</li>\n";
}
result += "</ul>\n";
return result;
}
private static string ConvertToItem(this HtmlHelper helper,MenuItem item)
{
if (item.Show)
{
return string.Format("<li><a href='{0}'>{1}</a></li>\n", helper.AttributeEncode(item.Link), helper.AttributeEncode(item.Label));
}
else { return ""; }
}
}
终于我在我的师父以下调用显示菜单。
finally i have a following call in my Master to display the menu.
<!-- Navigation -->
<%= Html.DisplayMenu(Model.NavigationMenu) %>
注:我有一个强类型母版与包含类型NavigationModel的财产NavigationMenu类型(BaseViewModel)
Note: I have a strongly typed MasterPage with the type (BaseViewModel) that contains the property NavigationMenu of type NavigationModel
连接在一起的一切。
在我的例子中我在每个操作方法提供我与一个ViewModel视图(继承我的BaseViewModel),然后建立菜单(使用,它的大部分工作,所以我不必再一个Builder方法在每一个操作方法键入它)。如果你不使用BaseViewModel,那么你需要找到另一种方式来建立导航模型,然后通过导航模型到你的母版。
In my example i have to supply my Views with a ViewModel (that inherits my BaseViewModel) at each action method to and then build the Menu (using a Builder Method that does most of the work so i don't have to re type it in every action method). If you don't use a BaseViewModel then you will need to find another way to build the Navigation Model and then pass the Navigation Model to your MasterPage.
对于我来说我觉得有一个强类型的母版,使事情变得更容易和更清洁。王威尔德在他 GolfTracker系列实现它们的一个很好的方式
For me i find having a strongly typed MasterPage to make things easier and cleaner. King wilder have a nice way of implementing them in his GolfTracker Series.
这篇关于鉴于分层菜单基于父子类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!