user2984548
user2984548

Reputation: 31

Render bootstrap dropdown menu with in c# MVC3 Html.ActionLink

Therefore I faced an issue with MVC ActionLink and bootstrap dropdown. I succeeded with simple menu extension where I passed such a parameters like strings and one bool. But now I am trying to make my own extension which could generate Bootstrap Dropdown and add selected css class to parent of the dropdown - "ONEofTHEdropdownITEMSselected" - when one of those items in dropdown is selected (when selecting dropdown item it routes to different controller there fore can be few or more controllers):

<a href="#" class="dropdown-toggle ONEofTHEdropdownITEMSselected" data-toggle="dropdown">Dropdown <b class="caret"></b></a>

and

<li class="dropdown">
    <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
    <ul class="dropdown-menu">
        <li><a href="~/area/controller1">Action1</a></li>
        <li><a href="~/area/controller2">Action2</a></li>
    </ul>
</li>

Below is my UI/MenuExtensions.cs what I am trying to achieve - to pass two parameters which could generate the bootstrap dropdown and I can manually insert new menu items in that dropdown.

public static class MenuExtensions
    {
        public static MvcHtmlString MenuItem(
            this HtmlHelper htmlHelper,
            string text,
            string action,
            string controller,
            string cssClass = "item",
            bool isController = false
        )
        {
            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) || isController) &&
                 string.Equals(currentController, controller, StringComparison.OrdinalIgnoreCase))
                li.AddCssClass("am-selected");

            li.InnerHtml = htmlHelper.ActionLink(text, action, controller, new { Area = "" }, new { @class = cssClass }).ToHtmlString();
            return MvcHtmlString.Create(li.ToString());
        }

      public static MvcHtmlString SelectMenu(
            this HtmlHelper htmlHelper,
            string cssClass,
            SelectMenuItem[] menuItems
        )
        {
            TagBuilder list = new TagBuilder("li")
            {
                InnerHtml = ""
            };
            string currentAction = htmlHelper.ViewContext.RouteData.GetRequiredString("action");
            string currentController = htmlHelper.ViewContext.RouteData.GetRequiredString("controller");

            foreach (SelectMenuItem menuItem in menuItems)
            {
                TagBuilder li = new TagBuilder("li")
                {
                    InnerHtml = htmlHelper.ActionLink(menuItem.Text, menuItem.Action, menuItem.Controller, null, new { }).ToHtmlString()
                };
                ul.InnerHtml += li.ToString();
            }

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

Here is the external class

 public class SelectMenuItem
    {
        public string Text { get; set; }
        public string Action { get; set; }
        public string Controller { get; set; }
        public bool IsVisible { get; set; }

        public SelectMenuItem()
        {
            IsVisible = true;
        }
    }

After that my html looks like this.

 @Html.SelectMenu("dropdown", new []{
                            new SelectMenuItem{ Text = "ViewOne", Controller = "Controller1", Action = "index", IsVisible = SystemUser.Current().IsAdmin},
                            new SelectMenuItem{ Text = "ViewTwo", Controller = "Controller2", Action = "index"}
                        });

The problem is SelectMenu renders only this:

<li></li>

Upvotes: 3

Views: 4659

Answers (1)

Dmitry Efimenko
Dmitry Efimenko

Reputation: 11203

No need to reinvent the wheel. With TwitterBootstrapMVC desired output is achieved with the following syntax:

@using (var dd = Html.Bootstrap().Begin(new DropDown("Dropdown").SetLinksActiveByControllerAndAction()))
{
    @dd.ActionLink("Action1", "index", "controller1")
    @dd.ActionLink("Action2", "index", "controller2")
}

Notice the extension method SetLinksActiveByControllerAndAction(). That's what makes links active based on current controller/action.


Disclaimer: I'm the author of TwitterBootstrapMVC.

You need to purchase a license if working with Bootstrap 3. For Bootstrap 2 it's free.

Upvotes: 4

Related Questions