【问题标题】:ASP.Net MVC: Recursive approach not showing nested childASP.Net MVC:递归方法不显示嵌套子级
【发布时间】:2018-03-22 15:24:34
【问题描述】:

我正在尝试在 ul/li 中显示嵌套数据,但未显示嵌套子项。查看我的代码,请告诉我那里有什么问题。

控制器:

public ActionResult Index()
{       
    List<MenuItem> allMenu = new List<MenuItem>
    {
        new MenuItem {Id=1,Name="Parent 1", ParentId=0},
        new MenuItem {Id=2,Name="child 1", ParentId=1},
        new MenuItem {Id=3,Name="child 2", ParentId=1},
        new MenuItem {Id=4,Name="child 3", ParentId=1},
        new MenuItem {Id=5,Name="Parent 2", ParentId=0},
        new MenuItem {Id=6,Name="child 4", ParentId=4}
    };

    List<MenuItem> mi = allMenu
    .Where(e => e.ParentId == 0) /* grab only the root parent nodes */
    .Select(e => new MenuItem
    {
        Id = e.Id,
        Name = e.Name,
        ParentId = e.ParentId,
        Children = allMenu.Where(x => x.ParentId == e.Id).ToList()
    }).ToList();

    ViewBag.menusList = mi;

    return View();
}

POCO 类:

public class MenuItem 
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int ParentId { get; set; }
    public virtual List<MenuItem> Children { get; set; }
}

查看:

@helper ShowTree(List<Scaffolding.Controllers.MenuItem> menusList)
{
    <ul>
        @foreach (var item in menusList)
        {
            <li>
                <span>@item.Name</span>
                @if (item.Children != null && item.Children.Any())
                {
                    @ShowTree(item.Children)
                }
            </li>
        }
    </ul>
}

@{
    var menuList = ViewBag.menusList as List<Scaffolding.Controllers.MenuItem>;
    @ShowTree(menuList);
}

如果您运行代码,您将看到孩子 4 没有显示哪个是孩子 3 的孩子。请告知我需要在代码中更改的内容。谢谢

【问题讨论】:

  • 如果"child 4""child 3" 的孩子,但"child 3" 本身就是孩子(因此ParentId 不为零,那么.Where(e =&gt; e.ParentId == 0) 这一行将过滤掉它并它永远不会像您需要的那样填充其Children 属性。
  • 此外,即使您删除了 where 子句,您仍然会遇到问题,即您需要对其进行多次传递才能使 MenuItems 像您需要的那样递归嵌套。
  • @Shelby115 你能纠正我的代码,这将适用于第 n 次嵌套,因为没有什么比在哪里更改代码更能想到的了。谢谢

标签: asp.net-mvc


【解决方案1】:

您的查询仅获取顶级元素 (ParentId == 0),然后仅填充其直接子元素。

您的查询需要更改以填充所有级别的所有子元素。请注意,您的 MeuItem 不需要 ParentId 属性。

// Group the items by parentId and project to MenuItem
var groups = allMenu.ToLookup(x => x.ParentId, x => new MenuItem
{
    Id = x.Id,
    Name = x.Name,
});
// Assign the child menus to all items
foreach (var item in allMenu)
{
    item.children = groups[item.Id].ToList();
}
// Return just the top level items
ViewBag.menusList = groups[0].ToList();

附带说明,请勿使用ViewBag。而是将模型传递给视图

return View(groups[0].ToList());

在视图中

@model List<MenuItem>
....
@ShowTree(Model);

【讨论】:

  • 感谢您的回答先生。现在我可以解决问题了。问题主要存在于剃须刀逻辑中,我可以通过此链接 mikesdotnetting.com/article/208/… 修复并获得帮助,非常感谢您的建议和支持。
  • 您不需要更改原始问题中的@helper 代码(您自己的答案毫无意义,甚至不正确)
  • 先生,我刚刚检查了代码,现在它正在工作。如果可能的话,请举一个例子说明为什么你说不正确?
  • 你甚至没有发现这个答案有用! (但您问题中的@helper 代码不需要更改)
  • 它实际上是一个.GroupBy(),它会立即执行——详细解释请参考this answer
【解决方案2】:

现在我可以解决我的问题了。问题出在剃须刀代码的逻辑上,我也评论了这一行//.Where(e =&gt; e.ParentId == 0),我在这里添加了工作代码。

@helper  ShowTree(List<NestedChild.Controllers.MenuItem> menu, int? parentid = 0, int level = 0)
{
    var items = menu.Where(m => m.ParentId == parentid);

    if (items.Any())
    {
        if (items.First().ParentId > 0)
        {
            level++;
        }

        <ul>
            @foreach (var item in items)
            {
            <li>
                @item.Name
            </li>
                @ShowTree(menu, item.Id, level);
            }
        </ul>
    }
}
@{
    var menuList = ViewBag.menusList as List<NestedChild.Controllers.MenuItem>;
    @ShowTree(menuList);
}

动作

public ActionResult Index()
{
    List<MenuItem> allMenu = new List<MenuItem>
    {
        new MenuItem {Id=1,Name="Parent 1", ParentId=0},
        new MenuItem {Id=2,Name="child 1", ParentId=1},
        new MenuItem {Id=3,Name="child 2", ParentId=1},
        new MenuItem {Id=4,Name="child 3", ParentId=1},
        new MenuItem {Id=5,Name="Parent 2", ParentId=0},
        new MenuItem {Id=6,Name="child 4", ParentId=4}
    };

    List<MenuItem> mi = allMenu
    //.Where(e => e.ParentId == 0) /* grab only the root parent nodes */
    .Select(e => new MenuItem
    {
        Id = e.Id,
        Name = e.Name,
        ParentId = e.ParentId,
        Children = allMenu.Where(x => x.ParentId == e.Id).ToList()
    }).ToList();

    ViewBag.menusList = mi;

    return View();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-04
    • 2017-07-08
    • 1970-01-01
    • 1970-01-01
    • 2019-05-27
    • 1970-01-01
    • 1970-01-01
    • 2018-05-28
    相关资源
    最近更新 更多