我想创建一个带递归元素的递归菜单。我的第一种方法是使用部分视图来重用代码。唉,当我运行代码时,它会抛出“System.InvalidOperationException”“Stack empty”错误。
我使用AutoMapper从Web服务映射数据,从而产生以下实体:
public interface INavigationItemContract
{
int Id { get; set; }
string Title { get; set; }
int ParentId { get; set; }
string Url { get; set; }
bool DisplayInMenu { get; set; }
decimal SortOrder { get; set; }
IEnumerable<IPageBaseContract> Pages { get; set; }
IEnumerable<INavigationItemContract> Sites { get; set; }
}
初始化菜单的部分视图(_Menu.cshtml):
@model IEnumerable<INavigationItemContract>
<div class="navbar navbar-default" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
@foreach (var navigationItem in Model)
{
@Html.Partial("_MenuItem", navigationItem);
}
</ul>
</div>
</div>
显示菜单项的部分(_MenuItem.cshtml):
@model INavigationItemContract
@if (Model.Pages != null && Model.Pages.Any())
{
if (Model.Pages.Count() == 1 || !Model.DisplayInMenu)
{
// Only one page, so this will be the default.
// Other option is that the pages should not be displayed, so then we'll only display the link to the site.
<li><a href="@Model.Url">@Model.Title</a></li>
}
else
{
<li>
<a href="#">@Model.Title</a>
<ul class="dropdown-menu">
@foreach (var page in Model.Pages)
{
<li><a href="@page.RelativeUrl">@page.Title</a></li>
}
@foreach (var site in Model.Sites)
{
@Html.Partial("_MenuItem", site)
}
</ul>
</li>
}
}
更换
时@Html.Partial("_MenuItem", site)
带
<li>@site.Title</li>
一切都像魅力一样(除了它不是理想的结果)。
我也尝试过以下方法:
_MenuItem.cshtml中发生异常:
@Html.Partial("_MenuItem", site)
第一次调用partial时(在_Menu.cshtml中),只有在_MenuItem.cshtml本身调用自身时才会发生。
为什么我会收到此异常?什么可能是解决方案?
答案 0 :(得分:2)
我找到了一个解决方法。异常仍然让我感到困惑,但我可以继续渲染菜单(即使我没有能力在帮助程序代码上设置断点)..
@model IEnumerable
@helper RecursiveMenuItem(INavigationItemContract menuItem)
{
if (menuItem.Pages != null && menuItem.Pages.Any())
{
if (menuItem.Pages.Count() == 1 || !menuItem.DisplayInMenu)
{
// Only one page, so this will be the default.
// Other option is that the pages should not be displayed, so then we'll only display the link to the site.
<li><a href="@menuItem.Url">@menuItem.Title</a></li>
}
else
{
<li>
<a href="#">@menuItem.Title</a>
<ul class="dropdown-menu">
@foreach (var page in menuItem.Pages)
{
<li><a href="@page.Url">@page.Title</a></li>
}
@foreach (var site in menuItem.Sites)
{
@RecursiveMenuItem(site)
}
</ul>
</li>
}
}
}
<div role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="">Home</a></li>
@foreach (var menuItem in Model)
{
@RecursiveMenuItem(menuItem)
}
</ul>
</div>
</div>
答案 1 :(得分:0)
不确定,但不应该通过替换来明确在模型中使用的枚举:
@foreach (var navigationItem in Model)
通过
@foreach (var navigationItem in Model.Sites)
例如?