3

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>

1 Answer 1

4

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Note that if you use Bootstrap 3 this requires a paid license. You can spend quite a bit of time perusing their documentation before this is mentioned.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.