Mvc 动态菜单填充纯文本

Mvc Dynamic Menu Populating plain text

我创建了创建菜单的第 N 级动态菜单递归方法。

如上图所示,内容返回到名为“_Menu.cshtml”的 ParialView,而这个 Partial View 文件是空的。

然后还有一个_LayoutPage.Cshtml

    <!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
</head>
<body>
    <div>
        <div>
            <input type="text" id="txtSearch" />
            <button id="btnSearch">Search</button>
         </div>
        <div id="Menu">
            @{Html.RenderAction("_Menu", "Home"); }
            @Html.Partial("_Menu")
        </div>
        <div>
            @RenderBody()
        </div>
    </div>
</body>
</html>

它成功地将结果放入浏览器,但作为我上面提到的纯文本,可以在下面看到。

我怎样才能让这些像链接一样,而不像纯文本?帮助将不胜感激。谢谢:)

我对此的看法稍微复杂一些。

在我放置的布局中...

 @if (Model != null && Model is Core.Objects.Entities.CMS.Page)
 {
                @Html.Action("Menu", new MenuOptions { IsRootMenu = true, ForPageId = Model.Id, Depth = 3 })
 }

我首先检查用户是否已登录,因此 "on a managed page" 只有当模型是特定类型时才会发生 "Core.Objects.Entities.CMS.Page"。

然后我调用@Html.Action,它在我的控制器上调用以下子操作,然后构建我的菜单选项...

[HttpGet]
[ChildActionOnly]
[Route("~/Menu")]
public ActionResult Menu(MenuOptions options)
{
    //TODO: consider other complex menuing scenarios like a popup / tree based structures
    //      New api calls may be needed to support more complex menuing scenarios

    // TODO: figure out how to build these, perhaps with a string builder
    var expand = string.Empty;
    if (options.Depth > 0)
    {
        switch (options.Depth)
        {
            case 1: expand = "?$expand=PageInfo,Pages($expand=PageInfo)"; break;
            case 2: expand = "?$expand=PageInfo,Pages($expand=PageInfo,Pages($expand=PageInfo))"; break;
            case 3: expand = "?$expand=PageInfo,Pages($expand=PageInfo,Pages($expand=PageInfo,Pages($expand=PageInfo)))"; break;
            case 4: expand = "?$expand=PageInfo,Pages($expand=PageInfo,Pages($expand=PageInfo,Pages($expand=Pages($expand=PageInfo))))"; break;
            case 5: expand = "?$expand=PageInfo,Pages($expand=PageInfo,Pages($expand=PageInfo,Pages($expand=PageInfo,Pages($expand=PageInfo,Pages($expand=PageInfo)))))"; break;
        }
    }

    var query = options.IsRootMenu
        ? "Core/Page/MainMenuFor(id=" + options.ForPageId + ")" + expand
        : "Core/Page/ChildrenOf(id=" + options.ForPageId + ")" + expand;

    var items = Task.Run(() => Api.GetODataCollection<Page>(query)).Result;

    return PartialView(new MenuViewModel { Origin = options.ForPageId, Pages = items });
}

在我的例子中,这方面需要做一些工作,我可能应该用一些更智能的循环代码来构建查询来替换那个 case 语句。

简而言之,虽然这一切所做的只是将 Page 对象的层次结构从我的 OData API 拉到由我传入的选项确定的深度,因为菜单往往会有所不同,有些是单级选项,有些则是多级但我想要一个可重复使用的菜单系统。

完成后,我可以获取 OData 结果并构建菜单视图模型,如下所示...

@model MenuViewModel
@if (Model.Pages != null)
{
    <ul class="menu">
        @foreach (var p in Model.Pages)
        {
            Html.RenderPartial("MenuItem", new MenuItemViewModel { Page = p, Origin = Model.Origin });
        }
    </ul>
}

菜单视图为根目录设置一个列表并为每个子页面呈现一个子页面,我计划在某些时候扩展这个视图,比如吐出可能在我拉入的 OData 结果中的父页面控制器。

最后一块拼图是处理呈现每个单独菜单项的菜单项视图...

@model MenuItemViewModel
<li>
    <a href="@Html.Raw("/" + Model.Page.Path)" @CurrentItem(Model.Page)>@Html.PageInfo(Model.Page).Title</a>
    @if (Model.Page.Pages != null && Model.Page.Pages.Any())
    {
        <ul class="submenu">
        @foreach (var p in Model.Page.Pages)
        {
            Html.RenderPartial("MenuItem", new MenuItemViewModel { Page = p, Origin = Model.Origin });
        }
        </ul>
    }
</li>

@functions{
    MvcHtmlString CurrentItem(Core.Objects.Entities.CMS.Page p)
    {
        if (Model.Origin == p.Id) return new MvcHtmlString("class='selected'");
        return null;
    }
}

完成所有这些后,我最终得到了一组嵌套列表,然后我使用 CSS 来处理弹出窗口或动态扩展等内容。

这个功能还不是很完整,我需要确保我用 class 或其他东西来处理 "marking the current item",这样我就可以设置不同的样式,还有一些我想要的其他菜单场景添加,但我也考虑过以某种方式将此 html 结构重用于树视图,但从长远来看,树可能会涉及更多,但做一些事情,比如将图像放在菜单项旁边似乎是一个很好的逻辑如果其可配置的改进 :)

我之前忘记放入的最后一件事是在控制器中的菜单操作中使用的菜单选项模型...

public class MenuOptions
{
    public bool IsRootMenu { get; set; }
    public int ForPageId { get; set; }
    public int Depth { get; set; }
}

尽管 War 解决了我上面的查询。但我仍然想为上述答案似乎很复杂的人回答。 在 MVC 中以最简单的方式从数据库填充动态导航菜单。

在控制器中:

    public ActionResult Index()
{
    Menu menu_ = new Menu();
    ViewBag.Menu = menu_.getMenuList();
    return View();
}

在_layoutpage.Cshtml

        <div id="Menu">
       @{ List<WebApplicationMVC.Core.Models.menu> All = ViewBag.Menu;}
        <ul>
            @foreach (var One in All.Where(m => m.ParentId == 0))
            {
                List<WebApplicationMVC.Core.Models.menu> Child = All.Where(m => One.id == m.ParentId).ToList();
                if (Child.Count > 0)
                {
                    if(One.ActionLink == "Yes")
                    {
                        <li>
                            @Html.ActionLink(One.Name, One.Action, One.Controller)
                            @SubMenu(One, All)
                        </li>
                    }
                    else
                    {
                        <li>
                            @One.Name;
                            @SubMenu(One, All)
                        </li>
                    }
                }
                else
                {
                    <li>@Html.ActionLink(One.Name, One.Action, One.Controller)</li>
                }
            }
        </ul>

        @helper SubMenu(WebApplicationMVC.Core.Models.menu Object, List<WebApplicationMVC.Core.Models.menu> List)
        {
        List<WebApplicationMVC.Core.Models.menu> subChilds = (from a in List where Object.id == a.ParentId select a).ToList();
        <ul>
            @foreach (var subOne in subChilds)
            {
                List<WebApplicationMVC.Core.Models.menu> InnerChilds = (from a in List where subOne.id == a.ParentId select a).ToList();
                if (InnerChilds.Count > 0)
                {
                    if (subOne.ActionLink == "Yes")
                    {
                        <li>
                            @Html.ActionLink(subOne.Name, subOne.Action, subOne.Controller)
                            @SubMenu(subOne, List)
                        </li>
                    }
                    else
                    {
                        <li>
                            @subOne.Name
                            @SubMenu(subOne, List)
                        </li>
                    }
                }
                else
                {
                    <li>@Html.ActionLink(subOne.Name, subOne.Action, subOne.Controller)</li>
                }
            }
        </ul>
        }
    </div>