Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

I'm using the codeplex cross-site collection navigation project as a basis. The problem should not be related to that specifically though.

I'm using Microsoft.SharePoint.WebControls.AspMenu as my navigation provider. In my masterpage I include a webpart that basically only collects some data (links) and creates and adds an AspMenu-control to the page. This all works fine, except one minor thing: The 'selected' class is never applied (it should be applied to the current/selected menu item). All the other classes (like 'static', 'dynamic', 'dynamic-children' etc.) are applied correctly to the menu list items.

SharePoint OOTB masterpage uses the same navigaton provider, except they include it directly in the masterpage, while I'm including a webpart that adds the menu control to the masterpage. Should be the same thing.

There seems to be some options available to configure this, but they are not working. For instance, it's possible to set the AspMenu's StaticSelectedStyle.CssClass, but the css class is never applied to the menu items.

Does anyone have a workaround for this problem?

share|improve this question
add comment

1 Answer 1

up vote 1 down vote accepted

I was unable to fix this issue as I would have preferred, however I was able to work around this by adopting the codeplex navigation project and manually choose which item that should be selected in the top menu.

If anyone else are having this issue, here's how it works. After iterating through all the items, the last step before Controls.Add(spMenu), I'm calling my custom method like the following:

     //Choose Currently selected item
     var requestUri = HttpContext.Current.Request.Url.AbsoluteUri;
     ChooseSelectedMenuItem(spMenu.Items, requestUri);

}
Controls.Add(spMenu);

The ChooseSelectedMenuItem is very simple. It iterates through the first level of menu items and selects the last item that starts with the same url as the current request's AbsoluteUri. It should select the last item in case we're including Home/Root in the menu - so we don't always select this node (every node usually starts with the same url as Home/Root). When an item has Selected=true, the correct 'selected' css-class is given in the final HTML.

private static void ChooseSelectedMenuItem(MenuItemCollection items, string requestUri)
{
    var urlToMatchOn = SPHttpUtility.UrlPathDecode(requestUri, true).TrimEnd('/').ToLower(CultureInfo.InvariantCulture);

    var matchingItems = new List<MenuItem>();
    foreach (MenuItem item in items)
    {
        var currentMenuItemUrl = SPHttpUtility.UrlPathDecode(item.NavigateUrl, true).TrimEnd('/').ToLower(CultureInfo.InvariantCulture);

        if (urlToMatchOn.StartsWith(currentMenuItemUrl)) matchingItems.Add(item);
    }
    if (matchingItems.Count > 0) matchingItems.Last().Selected = true;
}

Of course if a childnode should be selected instead of one of the topnodes, some extra logic is necessary. Hope this can be helpful to someone.

share|improve this answer
    
What did you end up doing for matchingItems.Last ? –  CeeMoney Apr 11 '12 at 13:11
    
If more than one item is matching, I'm selecting the last matched item, as that will (almost) always have the longest match, and therefore the most correct match. –  tarjeieo Apr 13 '12 at 8:58
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.