ASP.NET Forms Bootstrap Menu Control

UPDATE: I have closed the comments for this post. If you’d like to discuss the ASP.NET Forms Bootstrap Menu Control, please visit the GitHub repository located at: https://github.com/knight0323/aspnet-forms-bootstrap-menu


When I couldn’t find an ASP.NET Form menu control that was compatible with Bootstrap 3.1, I did what every other developer would do: I created one. Enjoy!

Here’s the HTML markup view:

<div class="navbar navbar-inverse navbar-static-top" role="navigation">
    <div class="container" style="padding: 0; margin: 0;">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
        </div>
        <div class="navbar-collapse collapse">
            <jk:BootstrapMenu ID="BootstrapMenu1" runat="server">
                <Items>
                    <asp:MenuItem Text="Home" NavigateUrl="#" />
                    <asp:MenuItem Text="About" NavigateUrl="#" />
                    <asp:MenuItem Text="Contact" NavigateUrl="#" />
                    <asp:MenuItem Text="Drop Down">
                        <asp:MenuItem Text="Action" NavigateUrl="#" />
                        <asp:MenuItem Text="Another action" NavigateUrl="#" />
                        <asp:MenuItem Text="Something else here" NavigateUrl="#" />
                    </asp:MenuItem>
                    <asp:MenuItem Text="Help" NavigateUrl="#" />
                    <asp:MenuItem Text="Nothing" />
                </Items>
            </jk:BootstrapMenu>
        </div><!--/.nav-collapse -->
    </div>
</div>

Here’s the HTML markup view for using with a SiteMapDataSource:

<div class="navbar navbar-inverse navbar-static-top" role="navigation">
    <div class="container" style="padding: 0; margin: 0;">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
        </div>
        <div class="navbar-collapse collapse">
            <jk:BootstrapMenu ID="BootstrapMenu2" runat="server" DataSourceId="SiteMapDataSource1" />
            <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" ShowStartingNode="False" />
        </div><!--/.nav-collapse -->
    </div>
</div>

In either case you’ll need a page directive

<%@ Register tagPrefix="jk" assembly="JK.Core.Web" namespace="JK.Core.Web.Controls" %>

Updates:

  • 2017 January 23: Closed comments to push conversation to GitHub repository.
  • 2015 January 19: Added zip file sample project for download to OneDrive.
  • 2014 August 15: Added page directive needed to use control in page markup
  • 2014 April 11: Updated to work with SiteMapDataSource
Advertisements

73 thoughts on “ASP.NET Forms Bootstrap Menu Control

  1. Yarik April 11, 2014 / 2:21 am

    Hi,

    How to get the Menu working when You set DataSourceID to SiteMapDataSource ?

    • Jeremy June 9, 2014 / 10:37 am

      Sorry about that. I hadn’t tested it with that and it got overlooked. It should be fixed now.

    • Rafael Reis December 5, 2014 / 1:14 pm

      Hi,

      Is there anyone who can provide me a basic 3 level collapsing menu for bootstrap navbar? I don’t manage to open the third level. Can someone adapt my code to add a third level?

      • Jeremy December 7, 2014 / 4:59 am

        Multi-level drop downs aren’t supported by Bootstrap. The Bootstrap team’s official stance on multi-level drop downs is:

        Not right now. I’m not convinced levels and levels of dropdowns are an ideal situation on any site or application
        Issue on Bootstrap GitHub

        The linked issue does give some insight as to why and discusses one alternative.

  2. faraz45pk April 21, 2014 / 8:04 am

    HI, what about the seleceted item is it highlighted

    • Jeremy June 9, 2014 / 10:47 am

      I can get it to work with binding to a SiteMap. In the BuildItem(), change

      if (item.ChildItems.Count > 0)
      {
      writer.AddAttribute(HtmlTextWriterAttribute.Class, “dropdown”);
      }

      to

      if (item.ChildItems.Count > 0)
      {
      writer.AddAttribute(HtmlTextWriterAttribute.Class, “dropdown”);
      }
      else if (item.Selected)
      {
      writer.AddAttribute(HtmlTextWriterAttribute.Class, “active”);
      }

  3. Phil April 28, 2014 / 10:15 am

    Have you updated the source on codeplex for this to work with a sitemap now?

    • Jeremy June 9, 2014 / 10:46 am

      Yes. It’s just the EnsureDataBound() in the OnPreRender().

  4. Andry June 7, 2014 / 8:50 am

    Hey this is what I have been looking for. Can you please tell me how to use the codes to get it fully working?

    • Jeremy June 9, 2014 / 10:24 am

      Andry, I’ve replied to your email.

      • Victor July 4, 2014 / 3:07 pm

        Hi many thanks for your help :), this is what I’m looking for. Can you explain me too? I’ll like to use it with a menu.sitemap. Many Thanks!

      • Jeremy July 7, 2014 / 1:54 pm

        Do you need help with installing the control, setting up the sitemap, configuring the web.config to use the sitemap, or a little of all of the above?

      • Victor July 7, 2014 / 2:45 pm

        Hi Jeremy,

        Yep, a little of all jeje, well.. Actually I have a project that use a normal ASP.NET Menu Control with sitemaps, for each role I use a different sitemap to render de Menu control, my code:

        NavigationMenu.DataSource = GetDataSource(rol, Server.MapPath(“~”));
        NavigationMenu.DataBind();

        Method:
        XmlDataSource GetDataSource(int UserRole, string ServerPath)
        {
        XmlDataSource oXmlDataSource = new XmlDataSource();
        oXmlDataSource.XPath = “siteMap/siteMapNode”;
        switch (UserRole)
        {
        case 1:
        oXmlDataSource.DataFile = ServerPath + @”/siteMaps/Administrador.sitemap”;
        break;
        ….}
        }

        My question is, how can I bind your control to the sitemaps and what method of your class I have to use.

        Many Thanks 🙂

      • Jeremy July 14, 2014 / 6:43 pm

        I’ve inherited the normal ASP.NET Menu control to build this control so you should be able to use the same DataSource property and DataBind method.

  5. Andrew Ames August 14, 2014 / 6:26 am

    dont get how to use this??? does it go in a user control or something else?

    • Jeremy August 15, 2014 / 11:48 am

      It goes into a class file in the project.

      You can actually drag it right in if you’ve downloaded it from my site. If you use this method, you’ll need to change the namespace at the top of the file to match the project you’re working in.

      – or –

      You can add a new class to the project named BootstrapMenu.cs and copy the code in. This method will put the right namespace in for you automatically.

      I’ve also updated the post above to show the page directive tag needed.

  6. Caprica October 22, 2014 / 9:27 pm

    Greetings Jeremy

    I felt that I must send you a big thank you for this control. I have been grappling with combining the advantages of Bootstrap with the advantages of ASP.NET and discovered you did it for me!!! I also learned about building a class library at the same time.

    You are a prince among men!
    Again thank you, thank you, thank you!!!

    • Jeremy November 14, 2014 / 3:24 am

      I’m glad I could help. I’ll actually be created an adapter version of this control when I get some free time.

  7. Lisa Monk November 24, 2014 / 12:34 pm

    Hey Jeremy. This is awesome! Can it work with a role-based sitemap? Thanks!

    • Jeremy November 24, 2014 / 5:05 pm

      I honestly haven’t tested it but it should work.

  8. Lisa Monk November 25, 2014 / 11:09 am

    It does! Sweet!! Thank you so much!!!! (I know – lots of exclamation points there but this really is sa-weeet.)

  9. Pavel Vanecek December 10, 2014 / 5:54 am

    Nice article and idea of course. Thank You very much for share. I have been tested it for a while, but I have a little probem with second (third, …) levels of submenu. Little arrow appears next to submenu title, but after click, the subsubmenu is not showing. Is it my own fault or this feature is not available?

    • Jeremy December 10, 2014 / 10:33 am

      Bootstrap doesn’t support flyout menus so unfortunately this can only go one down from top level.

  10. abman2000 December 30, 2014 / 5:28 pm

    Great Find.. I am using this control in Visual Studio 2013, 4.5 Framework, and Bootstrap 3.3.1. the control has successfully been implemented and all items work except the drop down. I added a second layer as shown above but cannot seem to get the sub-menu items to expand. I only need the one level from root and eventually want to wrap this with a custom role provider. Consider me a newbie to bootstrap so fire away if I missed something simple

  11. Pavel Vanecek January 12, 2015 / 12:49 pm

    Nice work Jeremy.
    Now i decided implement the functionality to display bootstrap (or awesome font) icons based on attribute of sitemap node. It could be useful in my opinion.
    Greetings from Pilsen 😉

    • Pavel Vanecek January 12, 2015 / 1:22 pm

      I tried make it a simple way in the menuitemdatabound event:

      e.item.Text = ” ” + e.item.text

      It works, but in a class is not implemented imageUrl properties. The example below does not work:

      Protected Sub BootstrapMenu_MenuItemDataBound(sender As Object, e As MenuEventArgs) Handles BootstrapMenu.MenuItemDataBound
      If Not String.IsNullOrEmpty(e.Item.ImageUrl) Then e.Item.Text = String.Format(” “, e.Item.ImageUrl) & e.Item.Text
      End Sub

      • Pavel Vanecek January 12, 2015 / 1:24 pm

        ops, in the “” should be ,
        and

      • Pavel Vanecek January 12, 2015 / 1:27 pm

        span elements fa fa-search are missing in code above (it was removed by the editor software)

      • Jeremy January 12, 2015 / 2:21 pm

        Maybe just parse the title attribute? So something like title=”[[envelope]] My Mail” where [[envelope]] is the glyphicon you’d like to use? I’m thinking this way for those not using sitemaps and loading from a database for example.

  12. Wilton Martins January 17, 2015 / 1:09 pm

    I couldn’t run this example because the TagPrefix is not working…help me please!!

    • Jeremy January 18, 2015 / 3:18 am

      Check the sample page source link at the bottom of the article. First things to look for is the Register tag at the top. Second thing I would check is the installation of the class. If those are all correct, clean the solution then rebuild. If you’re still having problems after trying all that, you can throw your code on pastebin for more help.

      • Wilton Martins January 18, 2015 / 2:07 pm

        Man it still not working i did everything that you told me…. from this tag on everything is underline green… i need to make this menu responsive from a school project so i need you to help me.. if you can send this sample to my fb or my email i would appreciate that very much

      • Jeremy January 19, 2015 / 5:02 pm

        I’ve added a third link to the links section with a zip file which has a VS2013 project.

  13. Christine April 10, 2015 / 2:21 pm

    Awesome! Works great, thanks so much for sharing this!

  14. Shahroz May 8, 2015 / 7:56 am

    Sir that great. What if I use with dynamic menu from web.sitemap

      • Shahroz Gul May 9, 2015 / 11:37 am

        Thank you for reply. I applied and using it. I want to thank you on call. If possible.
        One more thing in this menu user needs to click on menu and then the dropdown is open. Is it possible to expand the dropdown on hover?

      • Jeremy May 11, 2015 / 7:01 am

        I’ve never had to set up the bootstrap menu that way so I don’t know off the top of my head. I can look into it and get back to you if you’d like.

      • Shahroz May 11, 2015 / 7:40 am

        Thats great! One more school of thought is that can we make bootstrap accordion menu read from web.Sitemap?

  15. Andry May 18, 2015 / 6:11 am

    Hi Jeremy, I am trying to add menu item programmatically at Page_Load but it does not work:

    protected void Page_Load(object sender, EventArgs e)
    {
    if (!Page.IsPostBack)
    {
    MenuItem menuItem = new MenuItem(“Test”);
    bmMenu.Items.Add(menuItem);
    }
    }

    Nothing is added. Any tips why?

    • Jeremy May 27, 2015 / 9:14 am

      Unfortunately, I do not. That’s pretty close to what I’m doing in one of my projects actually.

      • Andry May 31, 2015 / 1:05 am

        at Site.Master I have

        Now I want to be able to add menu programmatically so at page_load I have:

        protected void Page_Load(Object sender, EventArgs e)
        {
        if (!IsPostBack)
        {
        MenuItem menuItem = bmMenu.Items[0];
        MenuItem subMenuItem = new MenuItem(“New Category”);
        menuItem.ChildItems.AddAt(0, subMenuItem);
        }
        }

        it returns index out of range error.

        If the normal ASP.Net Menu control is inherited, it should work right?

        Can you please help?

      • Jeremy May 31, 2015 / 9:57 pm

        What are you using to load the menu initially?

  16. Andry May 31, 2015 / 1:25 am

    bmMenu.Items.Count returns 0. Weird…

  17. Felix July 8, 2015 / 1:13 pm

    submenu items not showing up from the example given. Any idea why? A, using visual studio express 2013 and latest bootstrap library. Literally downloaded and run the project, didn’t change anything.

    • Jeremy July 23, 2015 / 3:13 pm

      It could have something to do with Express. Have you tried using Community Edition?

  18. Michael July 27, 2015 / 3:12 pm

    Cant believe it took me sooooo long to find this thread. Jeremy, your article is perfect and saved me countless headaches. Thank you!

  19. Samuel Simon Severua August 1, 2015 / 3:04 pm

    its really confusing with different name IDs in codeplex source and the tutorial’s…..

  20. Samuel Simon Severua August 1, 2015 / 3:10 pm

    I did with the codeplex code and at runtime;

    Parser Error Message: Could not load file or assembly ‘DL.Core.Web’ or one of its dependencies. The system cannot find the file specified.

  21. Samuel Simon Severua August 1, 2015 / 4:37 pm

    1 more question,
    Can somebody implement this on a master page?

    • Jeremy August 3, 2015 / 10:49 am

      Definitely! I actually don’t think I’ve used it outside of a master page in any of my production projects. I’ll look at doing a master page example. I’ll also look at cleaning up the IDs.

      • Samuel Simon Severua August 3, 2015 / 11:02 am

        so then help me our, theres quite a small error with my son.
        I did exactly as written and even re visited codeplex to make sure but seems the SamplePageSource in my project has some errors.

        I use sitemapDataSource and when i this piece of code <jk:BootstrapMenu ID … is underlined with a green color. And says Element jk is not known….

        my directive code

        and menu code

        Toggle navigation

        i even included the directive in web.config but still #$%^..

      • Jeremy August 5, 2015 / 12:54 pm

        I’d take another look at the <%@ Register tagPrefix="jk" assembly="JK.Core.Web" namespace="JK.Core.Web.Controls" %>. The ‘tagPrefix’ can be whatever you want. If you want to use tagPrefix=”custom” then your code would just look like custom:BootstrapMenu.

        The assembly is where you put the class file. If you put the class file in the a project called “MyProject” the default assembly name will be “MyProject”.

        The namespace will be in the class file itself. If you’re using the one off of my blog it’s “JK.Core.Web.Controls” and if you got it directly from the codeplex site it’s “DL.Core.Web.Controls”.

      • Sebastian December 3, 2015 / 9:03 am

        Hi Jeremy, I downloaded the code and works! I’m trying to do this on a exists web application, but I get the error “server label unknow: bootstrap:BootstrapMenu”..

        I have not a project, I have a “Web Site”, how should I reference the assembly?

        Thanks a lot!

  22. Robert September 13, 2015 / 3:29 pm

    I implemented the control but it keeps rendering the default html instead of the bootstrap implementation. I realy don’t get it, I added a constructor to the control to make sure the control is instantiated and it does. But the render methods aren’t being called.
    Any idea? thanks

    • Jeremy September 16, 2015 / 4:17 pm

      You may want to drop some snippets in pastebin or a site like it so I can give you some tips on what to look at.

      • Robert September 16, 2015 / 5:42 pm

        Great thanks! It’s very basic usage I guess: http://pastebin.com/bCg1U2Wb

        I don’t understand why the Render methods are not being called, but it does render html (how is that even possible!?)
        Also when I create a new web project and add the control the control works perfectly, so something in the project is messing with the rendering… Maybe it thinks its in designmode or something like that?

  23. Tarik Alkathiri September 16, 2015 / 11:13 am

    Great job thank you very much for sharing this.
    Can you please help me in how to disable item depending on user rights
    again thank you very much

    • Jeremy September 16, 2015 / 4:09 pm

      One of the examples uses the web.sitemap to do just this! 🙂

  24. Site October 25, 2015 / 10:23 pm

    Hi Jeremy:

    is there anyway solution to make the dynamic sidebar work in master page?
    i’m using ASP for my page, and the sidebar will only get data from table of sql server 2012.
    Any solution for this? thank you.

    • Jeremy October 28, 2015 / 9:03 am

      Something like Bootstrap’s Affix correct?

  25. Sunhwan Kim December 23, 2015 / 3:10 am

    Hi Jeremy~

    Thank you for sharing this component. it works great.
    I’m using multi level sitemap but I don’t know how to make it with this component.
    pls advise.

    Many thanks

  26. bob January 15, 2016 / 5:27 pm

    Your control looks intriguing, however I am somewhat of a novice with coding. I have a “WEB SITE” not “project”. I have created the class file “Menu.vb” in the App_Code directory. The namespace in the Menu.bc file is labeled ” FormsBootstrap”. I am not able to get the page directive to work. Can you please provide some guidance with the page directive syntax? The assembly portion of the directive seems to indicate that a dll file is needed? Am I missing a dll file somewhere?

    Thanks

    • Jeremy January 19, 2016 / 9:09 am

      It’s been a long time since I worked with a website instead of a project but my suggestion would be to try and get the control on the toolbox. If I remember correctly, the drag and drop functionality should wire up everything correctly at that point.

  27. Rick February 3, 2016 / 1:28 pm

    Hi Jeremy,

    Many thanks for your control! It was exactly what I looking for, however I can’t seem to get it working with a site map. I can only get the top level to appear. The site map provided with the download/example appears empty…

    When I use the following sitemap…

    with the following markup…

    … my menu only displays “TopNode1” and “TopNode2” with no dropdowns. Can you please advise?

    Thanks!

      • Rick February 4, 2016 / 2:00 pm

        Hi Jeremy, thanks for your reply. I’ve tried that with no luck. I’ve created a small sample project that illustrates the problem. It has your bootstrap menu on top of the regular asp menu. The asp menu has the sub items but the bootstrap menu does not. Could I send it to you to take a look? I love what you’ve done and I’d really like to get it working!

  28. Greg January 13, 2017 / 12:48 pm

    Had to make a few corrections….in addition there is no accommodation for one of the most important features….security trimming!!

    • Jeremy January 13, 2017 / 1:03 pm

      Share your corrections so I can review and add them in if needed. I’d have to look at your code to see what you’re doing but sitemap binding and security trimming has been confirmed to work by multiple people.

Comments are closed.