Marcus J. Maunula
Marcus J. Maunula

Reputation: 21

MVC2 Multilevel navigation

One question I have yet to find an answer on is this. How do I keep track of active Sitemap nodes on multiple levels?

For example :

How do I keep track of a childnode being active as well as the parent it belongs to being marked as active.

I know there is something called IsDescendant but I always get exceptions when using it due to null values.

Is there some screencast/tutorial on doing more advanced custom navigation in mvc.net(or asp.net for that matter). Most seem to deal with simple one level navigation.

I would prefer examples in C# if possible, thank you.

Upvotes: 2

Views: 961

Answers (1)

Manaf Abu.Rous
Manaf Abu.Rous

Reputation: 2417

Ok ,,, I've suffered from the same issue and I came up with a work around, check my answer in this question :

Hierarchical menu in view based on parent child class

I've been meaning to come up with a more generic elegant way of doing it since I've faced the problem but I've been busy ever since. I'm hoping I'll find some time in the next weeks to come up with something ,,,


Note : for simplicity in my solution in the above question in the methods DisplayMenu and ConvertToItem particularity, I've removed the parts where it should check for the currentMenuID and the currentMenuItemID fields and add the current css class to the li element (or active class in your case).

Since this is all what's your question is about, I've provided the full methods below.

public static string DisplayMenu(this HtmlHelper helper, NavigationModel navigationMenu)
    {            
        string classOfCurrentMenu;


        String result = "<ul id='main-nav'>\n";
        foreach(Menu menu in navigationMenu.Menus)
        {
            classOfCurrentMenu = "";
            if (menu.ID == navigationMenu.currentMenuID)
            {
                classOfCurrentMenu = "current";
            }

            result +=     "<li>\n";
            result +=         string.Format("<a href='#' class='{0}'> {1} </a>\n", helper.AttributeEncode(classOfCurrentMenu),helper.AttributeEncode(menu.Name));
            result +=         "<ul>\n";
            foreach(MenuItem item in menu.MenuItems)
            {
                result += NavigationHelper.ConvertToItem(helper, item, navigationMenu.currentMenuID, navigationMenu.currentMenuItemID);
            }
            result +=         "</ul>\n";
            result +=     "</li>\n";
        }
        result +=     "</ul>\n";

        return result;
    }


private static string ConvertToItem(this HtmlHelper helper,MenuItem item, int currentMenuID, int currentMenuItemID)
    {
        if (item.Show)
        {
            string classOfCurrentItem = "";
            if (item.ID == currentMenuItemID && item.MenuID == currentMenuID)
                classOfCurrentItem = "current";

            return string.Format("<li><a href='{0}' class='{1}'>{2}</a></li>\n", helper.AttributeEncode(item.Link), helper.AttributeEncode(classOfCurrentItem), helper.AttributeEncode(item.Label));
        }
        else { return ""; }   
    }

I don't consider this as a perfect solution to the problem, I hate writing HTML in C# code, I will try my best to come up with a more generic (multi level) cleaner solution for the problem, and of course make use of the TagBuilder class in the framework.

Upvotes: 1

Related Questions