MVCSitemapProvider indicate current node and parent node
Asked Answered
F

3

6

I would like to mark the current node and it's parent with a css class. I was searching around and found these links:

http://mvcsitemap.codeplex.com/discussions/257786 http://mvcsitemap.codeplex.com/discussions/245000

So I modified SiteMapNodeModelList.cshtml and now the current node is highlighted. But not sure how I should highlight the parent node.

<ul>
    @foreach (var node in Model) { 
        <li class="@(node.IsCurrentNode ? "current" : "")" >@Html.DisplayFor(m => node) 
            @if (node.Children.Any()) {
                @Html.DisplayFor(m => node.Children)
            }
        </li>
    }
</ul>

To mark the parent node I've built an extension method that checks all immediate child elements (I only have 2 levels):

    public static bool IsCurrentNodeOrChild(this SiteMapNodeModel node)
    {
        if (node.IsCurrentNode) return true;

        return node.Children.Any(n => n.IsCurrentNode);
    }

And changed MenuHelperModel.cshtml like this:

<ul id="menu">
    @foreach (var node in Model.Nodes) { 
        <li class="@(node.IsCurrentNodeOrChild() ? "current" : "d")" >@Html.DisplayFor(m => node) 
            @if (node.Children.Any()) {
                @Html.DisplayFor(m => node.Children)
            }
        </li>
    }
</ul>

This now works perfectly. But is there really no simpler approach? Can't be the first man on earth that needs this?

Farrel answered 22/11, 2013 at 16:59 Comment(0)
B
4

You may very well be the first person on Earth who needs this. Then again, I suspect that there are dozens of libraries of useful methods out there that could make MvcSiteMapProvider more useful.

MvcSiteMapProvider is an open source collaborative effort. If you spot something like this that could be useful to a great many people, we'd appreciate making a contribution by pull request @ GitHub on the dev branch. This idea would make a very nice contribution. I suggest adding the method to the SiteMapNodeModel object directly.

Bobker answered 23/11, 2013 at 3:32 Comment(4)
Thanks! This was not meant against MvcSiteMapProvider. I more had the feeling that I was missing something somewhere.Farrel
I've created a git pull. github.com/maartenba/MvcSiteMapProvider/pull/251 I hope I've done this correctly.Farrel
Sorry, for bringing this back from the dead, but is there a possibility to extend the SiteMapNodeModel with custom tags (e.g. for filtering the nodes)? I wanted to use the node.ResourceKey, but the node is inaccessible.Mendes
@Mendes - One option is to use custom attributes. Alternatively, see this answer. There are many options for controlling the display of nodes. Think of the SiteMap as sort of a hierarchial database. You must put all of the data you intend to use there. Then you can use visibility providers, security trimming, HTML helper templates, and/or custom HTML helpers to make views of the specific nodes you want to see in the page. Custom visibility providers have direct access to all of the fields of the node.Bobker
W
5

That is really, cool, but when I keep creating extensions for this and that, I took a different approach but I should note that it is based on your idea :D

MainMenu.cshtml:

@model MvcSiteMapProvider.Web.Html.Models.MenuHelperModel
@using MvcSiteMapProvider.Web.Html.Models

@foreach (var node in Model.Nodes)
{
   <li @((node.IsCurrentNode || node.Children.Any(n => n.IsCurrentNode)) ? "class=active" : "")>@Html.DisplayFor(m => node)</li>  
}

and insert this into

_Layout.cshtml

@Html.MvcSiteMap().Menu("MainMenu")

Basically it does the same thing, just a little bit cleaner (in my opinion)

Whittling answered 2/12, 2014 at 22:0 Comment(0)
B
4

You may very well be the first person on Earth who needs this. Then again, I suspect that there are dozens of libraries of useful methods out there that could make MvcSiteMapProvider more useful.

MvcSiteMapProvider is an open source collaborative effort. If you spot something like this that could be useful to a great many people, we'd appreciate making a contribution by pull request @ GitHub on the dev branch. This idea would make a very nice contribution. I suggest adding the method to the SiteMapNodeModel object directly.

Bobker answered 23/11, 2013 at 3:32 Comment(4)
Thanks! This was not meant against MvcSiteMapProvider. I more had the feeling that I was missing something somewhere.Farrel
I've created a git pull. github.com/maartenba/MvcSiteMapProvider/pull/251 I hope I've done this correctly.Farrel
Sorry, for bringing this back from the dead, but is there a possibility to extend the SiteMapNodeModel with custom tags (e.g. for filtering the nodes)? I wanted to use the node.ResourceKey, but the node is inaccessible.Mendes
@Mendes - One option is to use custom attributes. Alternatively, see this answer. There are many options for controlling the display of nodes. Think of the SiteMap as sort of a hierarchial database. You must put all of the data you intend to use there. Then you can use visibility providers, security trimming, HTML helper templates, and/or custom HTML helpers to make views of the specific nodes you want to see in the page. Custom visibility providers have direct access to all of the fields of the node.Bobker
M
0

This is a great posting!

while I disagree with a comment from another poster, this page had exactly what I was looking for. My customer's were getting lost in large menus with sub menus of submenus...while I am not a fan of it, that is what they wanted.

I would like to improve upon what Theodor had suggested. instead of using node.Children, use node.Descendants. that way if you are in a 2nd sublist, it still shows up all the way at the top!

@model MvcSiteMapProvider.Web.Html.Models.MenuHelperModel
@using System.Web.Mvc.Html
@using MvcSiteMapProvider.Web.Html.Models

@helper  TopMenu(List<SiteMapNodeModel> nodeList)
{
    <nav class="navbar navbar-default" role="navigation">
        <div class="container-fluid">
            <div class="collapse navbar-collapse">
                <ul class="nav navbar-nav">
                    @foreach (SiteMapNodeModel node in nodeList)
                    {
                        string url = node.IsClickable ? node.Url : "#";

                        if (!node.Children.Any())
                        {
                            <li class="@((node.IsCurrentNode || node.Descendants.Any(n => n.IsCurrentNode)) ? "active" : "")"><a href="@url">@node.Title</a></li>
                        }
                        else
                        {
                            <li class="dropdown @((node.IsCurrentNode || node.Descendants.Any(n => n.IsCurrentNode)) ? "active" : "")"><a class="dropdown-toggle" data-toggle="dropdown">@node.Title <span class="caret"></span></a>@DropDownMenu(node.Children)</li>
                        }

                        if (node != nodeList.Last())
                        {
                            <li class="divider-vertical"></li>
                        }
                    }
                </ul>
            </div>
        </div>
    </nav>
}

@helper DropDownMenu(SiteMapNodeModelList nodeList)
{
    <ul class="dropdown-menu" role="menu">
        @foreach (SiteMapNodeModel node in nodeList)
        {
            if (node.Title == "Separator")
            {
                <li class="divider"></li>
                continue;
            }

            string url = node.IsClickable ? node.Url : "#";

            if (!node.Children.Any())
            {
                <li class="@((node.IsCurrentNode || node.Descendants.Any(n => n.IsCurrentNode)) ? "active" : "d")"><a href="@url">@node.Title</a></li>
            }
            else
            {
                <li class="dropdown-submenu @((node.IsCurrentNode || node.Descendants.Any(n => n.IsCurrentNode)) ? "active" : "d")"><a href="@url">@node.Title</a>@DropDownMenu(node.Children)</li>
            }
        }
    </ul>
}

@TopMenu(Model.Nodes)
Moccasin answered 16/10, 2015 at 21:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.