Click here to Skip to main content
15,884,472 members
Articles / Web Development / ASP.NET
Tip/Trick

Highlight Current Menu Item under MvcSiteMapProvider

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
13 Feb 2017CPOL2 min read 8.5K   1  
Highlighting the current menu item in MVC using the MvcSiteMapProvider turned out to be somewhat of a challenge but with a little head scratching and several cups of coffee, this is what emerged.

The default MVC 5 setup gives you a horrendous menu to work with and I probably could have made it look half way decent but I remembered the old SiteMapProvider I had used many moons ago and wondered if there was anything like it available today. Turns out there is and it's available at https://github.com/maartenba/MvcSiteMapProvider. You can also do a package install...

Install-Package MvcSiteMapProvider.MVCx

...where x is the MVC version you are running.

Ok, so you got it configured and it looks pretty good but highlighting is a real PITA, I Googled for quite a while and the cleanest solution required is that you adorn one of the menu items with an 'selected' class attribute. Well, since you can't get to the element to add the said attribute, what can we do?

In the Mvc.sitemap file, the only thing that you are really allowed to set is the description field and when set, it overwrites the title field with what you entered in the description. So I got to thinking if I could get the current page and check it against the list of menu items and when I got a match, just set the menu items class to highlight the item.

So, given a very basic sitemap with just a few items:

XML
<mvcSiteMapNode title="Home" controller="Home"
action="Index" description="selected">
  <mvcSiteMapNode title="Pricing"
  controller="Pricing" action="Index" />
  <mvcSiteMapNode title="Contact"
  controller="Home" action="Contact"/>
  <mvcSiteMapNode title="Testimonials"
  controller="Testimonials" action="Index"/>
  <mvcSiteMapNode title="About"
  controller="Home" action="About"/>
  <mvcSiteMapNode title="Admin"
  controller="Admin" action="Index" roles="Admin" />
</mvcSiteMapNode>

As you can see, I set the Home menu item to selected and as long as it is unique, this scheme will work.

Now in your _Layout.cshtml file, add the JavaScript to do the actual work:

JavaScript
<script>
    window.onload = function () {
        setPage();
    }
 
    function setPage() {
        hrefString = document.location.href ? document.location.href : document.location;
 
        if (document.getElementById("menu") != null)
            setActiveMenu(document.getElementById("menu").getElementsByTagName("a"), 
                             extractPageName(hrefString));
    }
 
    function extractPageName(hrefString)
    {
        var arr = hrefString.split('/');
        return  arr[arr.length-1].toLowerCase();
    }
 
    function setActiveMenu(arr, crtPage)
    {
        for (var i=0; i < arr.length; i++)
        {
            if (extractPageName($($(arr[i])[0]).attr('href')) == crtPage)
            {
                if (arr[i].parentNode.tagName == "LI")
                {
                    arr[i].className = "current";
                }
            }
        }
    }
</script>

Then in your styles page, set the current class to whatever highlighting you desire, mine looks like this:

CSS
.current{
    color: #eab34f !important;
}

I got the code above from a site, don't remember where but I had to modify it to key on the title field and the parsing needed some work, but a lot of it came from him. Sorry dude, don't remember!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Retired
United States United States
Currently enjoying retirement and working on projects without pressure, deadlines or any kind of management.

Comments and Discussions

 
-- There are no messages in this forum --