【问题标题】:MVCSitemapProvider indicate current node and parent nodeMVSitemapProvider 指示当前节点和父节点
【发布时间】:2013-12-07 15:47:14
【问题描述】:

我想用一个 css 类标记当前节点和它的父节点。我四处寻找,发现了这些链接:

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

所以我修改了 SiteMapNodeModelList.cshtml,现在突出显示了当前节点。但不确定我应该如何突出显示父节点。

<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>

为了标记父节点,我构建了一个扩展方法来检查所有直接子元素(我只有 2 个级别):

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

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

并像这样更改 MenuHelperModel.cshtml:

<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>

现在可以完美运行了。但是真的没有更简单的方法吗?不能成为地球上第一个需要这个的人吗?

【问题讨论】:

    标签: c# asp.net-mvc mvcsitemapprovider asp.net-mvc-sitemap


    【解决方案1】:

    这是一个很棒的帖子!

    虽然我不同意另一位发帖人的评论,但这个页面正是我想要的。我的客户迷失在带有子菜单的子菜单的大菜单中......虽然我不喜欢它,但这正是他们想要的。

    我想改进 Theodor 的建议。而不是使用 node.Children,而是使用 node.Descendants。这样,如果您在第二个子列表中,它仍然会一直显示在顶部!

    @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)
    

    【讨论】:

      【解决方案2】:

      这真的很酷,但是当我继续为这个和那个创建扩展时,我采取了不同的方法,但我应该注意它是基于你的想法 :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>  
      }
      

      并将其插入

      _Layout.cshtml

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

      基本上它做同样的事情,只是更干净一点(在我看来)

      【讨论】:

        【解决方案3】:

        你很可能是地球上第一个需要这个的人。再说一次,我怀疑有几十个有用的方法库可以使 MvcSiteMapProvider 更有用。

        MvcSiteMapProvider 是一个开源协作项目。如果您发现这样的东西可能对很多人有用,我们将通过拉取请求@@GitHub on the dev branch 来感谢making a contribution。这个想法将做出非常好的贡献。我建议直接将方法添加到 SiteMapNodeModel 对象中。

        【讨论】:

        • 谢谢!这并不是针对 MvcSiteMapProvider。我更有一种感觉,我在某个地方错过了一些东西。
        • 我创建了一个 git pull。 github.com/maartenba/MvcSiteMapProvider/pull/251我希望我做对了。
        • 抱歉,让这个死而复生,但是否有可能使用自定义标签扩展 SiteMapNodeModel(例如,用于过滤节点)?我想使用node.ResourceKey,但是无法访问该节点。
        • @Storm - 一种选择是使用自定义属性。或者,请参阅this answer。有许多选项可用于控制节点的显示。将SiteMap 视为一种分层数据库。您必须将您打算使用的所有数据放在那里。然后,您可以使用可见性提供程序、安全修剪、HTML 帮助程序模板和/或自定义 HTML 帮助程序来查看您希望在页面中看到的特定节点。自定义可见性提供程序可以直接访问节点的所有字段。
        猜你喜欢
        • 1970-01-01
        • 2013-09-17
        • 2011-10-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-31
        相关资源
        最近更新 更多