是否存在用于可折叠(多级)Bootstrap 3菜单的简单MVC4 html帮助器? [英] Is there a simple MVC4 html helper for collapsible (multi-level) Bootstrap 3 menus?

查看:83
本文介绍了是否存在用于可折叠(多级)Bootstrap 3菜单的简单MVC4 html帮助器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看过有关为active菜单项创建HTML帮助器方法的几个示例.

I have seen several examples on creating a HTML helper method for active menu items.

**Summary:**简而言之,在MVC项目中,使用Twitter Bootstrap,我试图在选择子项时保留可折叠菜单的打开状态.

**Summary:** Simply put, in an MVC project, using the Twitter Bootstrap, I am trying to preserve the open state of a collapsible menu when a child is selected.

我正在使用可折叠菜单,如果选择了孩子,则父母的css(所选项目)需要包含active open.这将确保菜单在正确的位置打开.通过使用另一个HTML帮助器,活动项目已经设置为active.

I am using a collapsible menu, where the parent's css (the selected item) needs to include active open if a child is selected. This will ensure that the menu is open at the right location. With the use of another HTML helper, the active item is already set to active.

菜单的HTML:

    <div id="sidebar">
        <ul>
            <li class="active"><a href="dashboard.html"><i class="icon-home"></i> <span>Dashboard</span></a></li>
            <li class="submenu">
                <a href="#"><i class="icon-beaker"></i> <span>UI Lab</span> <i class="arrow icon-chevron-right"></i></a>
                <ul>
                    <li><a href="interface.html">Interface Elements</a></li>
                    <li><a href="jquery-ui.html">jQuery UI</a></li>
                    <li><a href="buttons.html">Buttons &amp; icons</a></li>
                </ul>
            </li>
            <li class="submenu">
                <a href="#"><i class="icon-th-list"></i> <span>Form elements</span> <i class="arrow icon-chevron-right"></i></a>
                <ul>
                    <li><a href="form-common.html">Common elements</a></li>
                    <li><a href="form-validation.html">Validation</a></li>
                    <li><a href="form-wizard.html">Wizard</a></li>
                </ul>
            </li>
            <li><a href="tables.html"><i class="icon-th"></i> <span>Tables</span></a></li>
            <li><a href="grid.html"><i class="icon-th-list"></i> <span>Grid Layout</span></a></li>
            <li class="submenu">
                <a href="#"><i class="icon-file"></i> <span>Sample pages</span> <i class="arrow icon-chevron-right"></i></a>
                <ul>
                    <li><a href="invoice.html">Invoice</a></li>
                    <li><a href="chat.html">Support chat</a></li>
                    <li><a href="calendar.html">Calendar</a></li>
                    <li><a href="gallery.html">Gallery</a></li>
                    <li><a href="messages.html">Messages</a></li>
                </ul>
            </li>
            <li>
                <a href="charts.html"><i class="icon-signal"></i> <span>Charts &amp; graphs</span></a>
            </li>
            <li>
                <a href="widgets.html"><i class="icon-inbox"></i> <span>Widgets</span></a>
            </li>
        </ul>

    </div>

这是项目的帮助方法:

    public static MvcHtmlString MenuItem(this HtmlHelper htmlHelper,
        string text,
        string action,
        string controller,
        string iconClass)
    {
        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");
        }

        var i = new TagBuilder("i");
        i.AddCssClass(iconClass);

        var basePath = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority);

        //li.InnerHtml = htmlHelper.ActionLink("<i>something</i>" + text, action, controller).ToHtmlString();
        li.InnerHtml = htmlHelper.Raw(string.Format("<a href=\"{0}/{1}/{2}\"><i class=\"{4}\"></i>{3}</a>", basePath, controller, action, text, iconClass)).ToString();

        return MvcHtmlString.Create(li.ToString());
    }

并这样实现:

        <div id="sidebar">
            <ul>
                @Html.MenuItem("Dashboard", "Index", "Dashboard", "icon-home")
@*              <li class="active"><a href="dashboard.html"><i class="icon-home"></i> <span>Dashboard</span></a></li>*@
                <li class="submenu">
                    <a href="#"><i class="icon-beaker"></i> <span>UI Lab</span> <i class="arrow icon-chevron-right"></i></a>

                    <ul>
                        <li>@Html.MenuItem("Websites", "Index", "Websites", null)</li>
                        <li><a href="jquery-ui.html">jQuery UI</a></li>
                        <li><a href="buttons.html">Buttons &amp; icons</a></li>
                    </ul>
                </li>
                <li class="submenu">
                    <a href="#"><i class="icon-th-list"></i> <span>Form elements</span> <i class="arrow icon-chevron-right"></i></a>
                    <ul>
                        <li><a href="form-common.html">Common elements</a></li>
                        <li><a href="form-validation.html">Validation</a></li>
                        <li><a href="form-wizard.html">Wizard</a></li>
                    </ul>
                </li>

所以我没有的是子菜单项.

So what I don't have is something for the submenu items.

有没有更简单的方法来实现这一目标?

Is there a simpler way of trying to accomplish this?

-更新-

我猜想把它放到局部视图中可能是最好的.我需要找到某种方法来保存选定的项目,并单击以在每个菜单项上对其进行引用,而不是检查控制器/操作是否匹配,以便将当前项目设置为活动".单击时激活的控制器方法,检查当前选择的项目是父项还是子项,以及父项是否与子项匹配,然后采用不同的格式?我敢肯定必须有一种更简单的方法.

I'm guessing that putting this into a partial view may be best. I need to find some way to preserve the selected item on click to reference it on every menu item, rather than check if the controller/action matches in order to set the current item to "active". A controller method that activates on click, checks if the currently selected item is a parent or child, and if the parent matches a child, then format differently? I'm sure there has to be an easier way.

推荐答案

好的,这是我想出的一种解决方案.

Alright, so here is one solution I came up with.

回顾一下,这并不像在项目中添加活动的" CSS类那么简单(根据默认的Bootstrap MVC.在此解决方案中,我们需要标识的父级和子级并标识两者.

To recap, this isn't as simple as adding an "active" CSS class to an item if it is selected (as per the default Bootstrap MVC. In this solution we need to identify the parent of and a child and identify both.

默认页面为仪表板.然后,用户单击配置"以展开菜单,然后选择网站"链接以打开页面.

Default page is Dashboard. The user then clicks on "Configuration" to expand the menu, then selects the "Websites" link which opens the page.

这是解决方案:

型号:

public class NavigationMenu
{
    public string Text { get; set; }
    public string Action { get; set; }
    public string Controller { get; set; }
    public string Icon { get; set; }
    public bool Selected { get; set; }

    public List<NavigationMenu> MenuChildren;
}

控制器:

public class NavigationController : Controller
{
    [ChildActionOnly]
    public ActionResult GenerateMenu()
    {
        List<NavigationMenu> menuItems = new List<NavigationMenu>();
        // build the menu
        menuItems.Add(new NavigationMenu
        {
            Text = "Dashboard",
            Action = "",
            Controller = "Dashboard",
            Icon = "icon-home",
            Selected = true,    // default selected menu item
            MenuChildren = null
        });
        menuItems.Add(new NavigationMenu
        {
            Text = "Configuration",
            Action = null,
            Controller = null,
            Icon = "icon-cog",
            MenuChildren = new List<NavigationMenu>{
                new NavigationMenu{
                    Text = "Websites",
                    Action = "",
                    Controller = "Websites",
                    Icon = null,
                    MenuChildren = null
                },
                new NavigationMenu{
                    Text = "Child 2",
                    Action = null,
                    Controller = null,
                    Icon = null,
                    MenuChildren = null
                }
            }
        });
        menuItems.Add(new NavigationMenu
        {
            Text = "Item 2",
            Action = "",
            Controller = "Item2",
            Icon = "icon-random",
            MenuChildren = null
        });
        menuItems.Add(new NavigationMenu
        {
            Text = "Item 3",
            Action = "",
            Controller = "Item3",
            Icon = "icon-certificate",
            MenuChildren = null
        });

        string action = ControllerContext.ParentActionViewContext.RouteData.Values["action"].ToString() == "Index" ? "" : ControllerContext.ParentActionViewContext.RouteData.Values["action"].ToString();
        string controller = ControllerContext.ParentActionViewContext.RouteData.Values["controller"].ToString();

        foreach (var item in menuItems)
        {
            if (item.MenuChildren != null)
            {
                foreach (var cItem in item.MenuChildren)
                {
                    if (cItem.Controller == controller && cItem.Action == action)
                    {
                        cItem.Selected = true;
                        break;
                    }
                    else
                    {
                        cItem.Selected = false;
                    }
                }
            }
            if (item.Controller == controller && item.Action == action)
            {
                item.Selected = true;
                break;
            }
            else
            {
                item.Selected = false;
            }
        }

        return PartialView("~/Views/Shared/_Navigation.cshtml", menuItems); 
    }

}

共享视图:

@model IEnumerable<AdminWebsite.Models.NavigationMenu>
@{
    var basePath = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority);
}
<div id="sidebar">
    @Html.Raw("<ul>")
        @foreach (var item in Model)
        {
            // if the menu item does not have children then it should be clickable
            if (item.MenuChildren == null & item.Selected)
            {
                <li class="active"><a href="@String.Format("{0}/{1}/{2}", basePath, item.Controller, item.Action)"><i class="@item.Icon"></i> <span>@item.Text</span></a></li>
            }
            else if (item.MenuChildren == null & !item.Selected)
            {
                <li><a href="@String.Format("{0}/{1}/{2}", basePath, item.Controller, item.Action)"><i class="@item.Icon"></i> <span>@item.Text</span></a></li>
            }

            // has children and one of its children is selected
            if (item.MenuChildren != null)
            {
                if (item.MenuChildren.Any(c => c.Selected) == true)
                {                
                    <text><li class="submenu active open"></text>
                }
                else
                {
                    <text><li class="submenu"></text>
                }

                // sub-menu parent
                if (item.MenuChildren != null & item.Selected)
                {
                    <a href="@String.Format("{0}/{1}/{2}", basePath, item.Action, item.Controller)"><i class="@item.Icon"></i> <span>@item.Text</span></a>
                }
                else if (item.MenuChildren != null & !item.Selected)
                {
                    <a href="@String.Format("{0}/{1}/{2}", basePath, item.Action, item.Controller)"><i class="@item.Icon"></i> <span>@item.Text</span></a>
                }

                // children
                <text><ul></text>
                    // iterate through children
                    foreach(var cItem in item.MenuChildren)
                    {
                        if (cItem.MenuChildren == null & cItem.Selected)
                        {
                            <li class="active"><a href="@String.Format("{0}/{1}/{2}", basePath, cItem.Controller, cItem.Action)"><i class="@cItem.Icon"></i> <span>@cItem.Text</span></a></li>
                        }
                        else if (cItem.MenuChildren == null & !cItem.Selected)
                        {
                            <li><a href="@String.Format("{0}/{1}/{2}", basePath, cItem.Controller, cItem.Action)"><i class="@cItem.Icon"></i> <span>@cItem.Text</span></a></li>
                        }                    
                    }

                @Html.Raw("</ul>");


                @Html.Raw("</li>");
            }

        }
    @Html.Raw("</ul>")
</div>

视图中的实现:

@{Html.RenderAction("GenerateMenu", "Navigation");}

控制器检查当前动作/控制器名称是否与菜单上的名称匹配,如果匹配,则设置selected = true.在局部视图中,有一些逻辑可以根据父/子关系确定显示结构,如果选择了子级,那么父级也是如此.

The controller checks if the current action/controller names match one on the menu and if so, set selected = true. In the partial view, there is some logic to determine the display structure, based on the parent/child relationships, and if a child is selected, so is the parent.

总之就是这样.我想听听一些评论/其他示例.

In brief, that's it. I'd like to hear some comments/other examples.

这篇关于是否存在用于可折叠(多级)Bootstrap 3菜单的简单MVC4 html帮助器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆