MvcSiteMapProvider 隐藏带有 CRUD 操作的 mvcSiteMapNode

MvcSiteMapProvider hidden mvcSiteMapNode with CRUD operation

在一个项目中,我实现了非常有效的 MvcSiteMapProvider。 这是一个用@Html.MvcSiteMap().Menu()

生成的侧边菜单

这是菜单的一个节点(Mvc.sitemap 文件)。

<mvcSiteMapNode title="Home" controller="Home" action="Index">
<mvcSiteMapNode title="About" controller="Home" action="About"/>
<mvcSiteMapNode title="Project" controller="Home" action="DummyAction">
  <mvcSiteMapNode title="List" controller="Home" action="Project"/>
  <mvcSiteMapNode title="Edit" controller="Home" action="Edit" preservedRouteParameters="id" visibility="SiteMapPathHelper,!*"/>
</mvcSiteMapNode>

当我从 "Project" 加载 "List" 时,它会显示一个包含所有项目的页面,我可以 select 其中之一加载具有相关 ID 的编辑操作项目。

问题是,当我在“编辑”操作页面中时,侧边菜单全部折叠,但我希望打开 "Project" 节点。如果我在菜单中添加节点 "Edit",它可以工作(匹配节点操作),但我不想要这个节点,因为它对用户没用。

此外,我已经尝试了 DefaultSiteMapNodeVisibiltyProvider,如果添加,我可以隐藏 "Edit" 节点,但是当我在 "Edit" 操作页面中时,项目节点也会关闭。

对于 "New/Add" 操作,我将面临同样的问题,我不想在侧边菜单中看到它,但可以从项目列表中的 link 访问它。但是,对于这些操作,我想让用户知道它在 "Project" 部分内,并打开了 "Project" 节点。

在 GitHub 上查看此项目: Project on Github

此致,

您的问题似乎是您没有考虑 Menu HTML 助手的递归性质。 Menu 交互的模板有 3 个:

  1. MenuHelperModel.cshtml
  2. SiteMapNodeModelList.cshtml
  3. SiteMapNodeModel.cshtml

问题是您没有向 SiteMapNodeModelList.cshtml 添加适当的逻辑。此外,MenuHelperModel.cshtml中的逻辑过于复杂。

处理同一页面上的 MenuSiteMapPath HTML 助手的一个好方法是使用命名模板而不是编辑默认模板。

BootstrapMenuHelperModel.cshtml

@model MvcSiteMapProvider.Web.Html.Models.MenuHelperModel
@using System.Web.Mvc.Html
@using MvcSiteMapProvider.Web.Html.Models
<ul id="menu" class="nav sidebar-menu">
    @foreach (var node in Model.Nodes)
    {
        string nodeclass = "";
        if (node.IsInCurrentPath && !node.IsRootNode)
        {
            nodeclass = "active";
            if (node.Children.Any())
            {
                nodeclass += " open";
            }
        }

        <li class="@nodeclass">
            @Html.DisplayFor(m => node)
            @if (node.Children.Any())
            {
                // Here we refer to a named template BootstrapMenuNodeModelList.cshtml
                @Html.DisplayFor(m => node.Children, "BootstrapMenuNodeModelList")
            }
        </li>
    }
</ul>

BootstrapMenuNodeModelList.cshtml

@model MvcSiteMapProvider.Web.Html.Models.SiteMapNodeModelList
@using System.Web.Mvc.Html
@using MvcSiteMapProvider.Web.Html.Models
<ul>
    @foreach (var node in Model)
    {
        string nodeclass = "";
        if (node.IsInCurrentPath && !node.IsRootNode)
        {
            nodeclass = "active";
            if (node.Children.Any())
            {
                nodeclass += " open";
            }
        }

        <li class="@nodeclass">
            @Html.DisplayFor(m => node)
            @if (node.Children.Any())
            {
                // Here we refer to a named template BootstrapMenuNodeModelList.cshtml,
                // which happens to be a recursive call to this template.
                @Html.DisplayFor(m => node.Children, "BootstrapMenuNodeModelList")
            }
        </li>
    }
</ul>

用法

在这里,我们告诉 Menu HTML 帮助程序使用名为 BootstrapMenuHelperModel.cshtml.

的自定义模板
@Html.MvcSiteMap().Menu("BootstrapMenuHelperModel")

NOTE: You could also create a custom template for the SiteMapNodeModel using the same approach. You would just need to call the overload in the other templates to use your template name.

Example:

Change @Html.DisplayFor(m => node) to @Html.DisplayFor(m => node, "MyTemplate") and create a corresponding file named MyTemplate.cshtml in the /Views/Shared/DisplayTemplates/ folder.