MvcSiteMapProvider 隐藏 mvcSiteMapNode 与 CRUD 操作 [英] MvcSiteMapProvider hidden mvcSiteMapNode with CRUD operation

查看:21
本文介绍了MvcSiteMapProvider 隐藏 mvcSiteMapNode 与 CRUD 操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在一个项目中,我实现了很好用的 MvcSiteMapProvider.这是一个用@Html.MvcSiteMap().Menu()

生成的侧边菜单

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

<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" reservedRouteParameters="id" visibility="SiteMapPathHelper,!*"/></mvcSiteMapNode>

当我从项目"加载列表"时,它会显示一个包含所有项目的页面,我可以选择其中一个来加载具有项目相关 ID 的编辑操作.

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

另外,我尝试了 DefaultSiteMapNodeVisibiltyProvider,如果添加,我可以隐藏编辑"节点,但是当我在编辑"操作页面时,项目节点也会关闭.

对于我不想在侧边菜单中看到的新建/添加"操作,我将面临同样的问题,但可以通过项目列表中的链接访问.但是,对于这些操作,我想让用户知道它在项目"部分内,并且项目"节点已打开.

在 GitHub 上查看此项目: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@使用 System.Web.Mvc.Html@using MvcSiteMapProvider.Web.Html.Models<ul id="menu" class="nav sidebar-menu">@foreach(Model.Nodes 中的 var 节点){字符串节点类 = "";if (node.IsInCurrentPath && !node.IsRootNode){nodeclass =活动";如果 (node.Children.Any()){nodeclass += "打开";}}
  • @Html.DisplayFor(m => 节点)@if (node.Children.Any()){//这里我们引用了一个命名模板 BootstrapMenuNodeModelList.cshtml@Html.DisplayFor(m => node.Children, "BootstrapMenuNodeModelList")}
  • }

    BootstrapMenuNodeModelList.cshtml

    @model MvcSiteMapProvider.Web.Html.Models.SiteMapNodeModelList@使用 System.Web.Mvc.Html@using MvcSiteMapProvider.Web.Html.Models<ul>@foreach(模型中的 var 节点){字符串节点类 = "";if (node.IsInCurrentPath && !node.IsRootNode){nodeclass =活动";如果 (node.Children.Any()){nodeclass += "打开";}}
  • @Html.DisplayFor(m => 节点)@if (node.Children.Any()){//这里我们引用了一个命名模板BootstrapMenuNodeModelList.cshtml,//这恰好是对该模板的递归调用.@Html.DisplayFor(m => node.Children, "BootstrapMenuNodeModelList")}
  • }

    用法

    在这里,我们告诉 Menu HTML 帮助程序使用名为 BootstrapMenuHelperModel.cshtml 的自定义模板.

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

    <块引用>

    注意:您还可以使用相同的方法为 SiteMapNodeModel 创建自定义模板.您只需要调用其他模板中的重载即可使用您的模板名称.

    示例:

    @Html.DisplayFor(m => node) 改为 @Html.DisplayFor(m => node, "MyTemplate") 并创建对应的文件在 /Views/Shared/DisplayTemplates/ 文件夹中命名为 MyTemplate.cshtml.

    In a project, i've implemented MvcSiteMapProvider that work great. This is a side menu generated with @Html.MvcSiteMap().Menu()

    Here is a node of the menu (Mvc.sitemap file).

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

    When I load the "List" from "Project", it displays a page with all projects and I can select one of them to load the Edit action with the related ID of the project.

    The problem is, when I'm in the Edit action page, the side menu is all collapsed, but I'm expecting to have the "Project" node opened. If I add the node "Edit" in the menu, it work (matching node action), but I don’t want this node because its useless for the user.

    Also, I've tried the DefaultSiteMapNodeVisibiltyProvider, I can hide the "Edit" node if added, but when I'm in the "Edit" action page, the Project node is also closed.

    I'll face the same problem for the "New/Add" operation that I don’t want to see in the side menu, but will be accessible from a link in the project list. However, for these operations, I want to let the user know that it is inside the "Project" section, with the "Project" node opened.

    See this project on GitHub: Project on Github

    Best regards,

    解决方案

    Your issue appears to be that you haven't accounted for the recursive nature of the Menu HTML helper. There are 3 templates that the Menu interacts with:

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

    The problem is that you haven't added the appropriate logic to the SiteMapNodeModelList.cshtml. In addition, the logic in the MenuHelperModel.cshtml is overly complex.

    A good approach for dealing with both a Menu and SiteMapPath HTML helper on the same page with customizations is to use named templates rather than editing the default templates.

    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>
    

    Usage

    Here, we tell the Menu HTML helper to use our custom template named 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.

    这篇关于MvcSiteMapProvider 隐藏 mvcSiteMapNode 与 CRUD 操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆