-1

I am beginner programmer. I am trying to display hierarchy but one nested child menu is not showing. I guess there is an error in my logic but not being able to find. Anyone mind to point out the area for which one child menu called child 4 is not showing in UI.

Here is code

public ActionResult Index()
{
    List<MenuItem> mi = 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}
    };
    ViewBag.menusList = mi;
    return View();
}


public class MenuItem
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int ParentId { get; set; }
}

Razor code

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

@if (menusList != null)
{
    <ul id="menu">
        @foreach(var parentMenu in menusList.Where(p => p.ParentId == 0))
        {
        <li>
            <span>@parentMenu.Name</span>
            @if (menusList.Count(p => p.ParentId == parentMenu.Id) > 0)
            {
                <ul id="menu">
                    @foreach(var childMenu in menusList.Where(p => p.ParentId == parentMenu.Id))
                    {
                        <li>
                            <span>@childMenu.Name</span>
                        </li>
                    }
                </ul>
            }
        </li>
        }
    </ul>
}

UI looks like enter image description here

thanks in advance.

EDIT

i have changed the code and now getting error called

CS1502: The best overloaded method match for 'ASP._Page_Views_Menu_Index_cshtml.ShowTree(System.Collections.Generic.List)' has some invalid arguments

still my code is not working. here is updated code

razor code

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


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

Action code

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<MenuDTO> mi = allMenu
    .Select(e => new
    {
        Id = e.Id,
        Name = e.Name,
        ParentId = e.ParentId,
        Children = allMenu.Where(x => x.ParentId == e.Id).ToList()
    }).ToList()
    .Select(p => new MenuDTO
    {
        Id = p.Id,
        Name = p.Name,
        ParentId = p.ParentId,
        Children = allMenu.Where(x => x.ParentId == p.Id).ToList()
    }).ToList();

    ViewBag.menusList = mi;

    return View();
}

Class code

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

public class MenuDTO 
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int ParentId { get; set; }
    public virtual ICollection<MenuItem> Children { get; set; }
}
Mist
  • 684
  • 9
  • 30
  • You have 3 levels deep, but only 2 nested `foreach` loops. But using nested foreach loops is not the correct approach (what if you later have 4 or 5 levels). You need a recursive function. –  Mar 15 '18 at 20:50
  • Do you really need a 3 levels menu, or it was just a typo? Which one is the parent of Child4 actually? I'm just curious. – Erlangga Hasto Handoko Mar 16 '18 at 04:32
  • @StephenMuecke yes you are right there could be nth level nesting.so need recursive. would you structure my code using recursive function which will work for nth nesting structure. – Mist Mar 16 '18 at 07:40
  • 1
    If this is something you do regularly, and might use in multiple projects, I would consider a `HtmlHelper` extension method (refer [this answer](https://stackoverflow.com/questions/27146524/how-to-render-singly-linked-list-in-mvc-view-page/27147744#27147744) for an example. Otherwise you could use a `@helper` method in the view –  Mar 16 '18 at 07:47
  • @StephenMuecke thank you sir. the moment i could fix this problem i will let you know with my updated code. i am doing this just for learning purpose. – Mist Mar 16 '18 at 07:56
  • @Mist, Sorry, I meant to include [this Q/A](https://stackoverflow.com/questions/19213000/asp-net-mvc-generating-multi-level-menu-using-recursive-helpers) in my previous comment as an example of a `@helper` method that can be used recursively –  Mar 17 '18 at 05:18
  • @StephenMuecke yes i followed but still not luck. i have include my full example under edit section. please sir see and tell me why i am getting the error and what to change in code to make it work. thanks – Mist Mar 20 '18 at 14:19
  • @StephenMuecke Sir i have posted my problem with a new thread in more details. here is link https://stackoverflow.com/questions/49392969/asp-net-mvc-how-to-show-nested-parent-child-relation-using-recursive-technique if possible guide and tell me how to restructure my code what i am trying to achieve. thanks in advance. – Mist Mar 20 '18 at 19:50
  • @Mist, The answer by user9525052 is correct. You not passing the correct type :) –  Mar 21 '18 at 02:19
  • @StephenMuecke sir i have one request that can you please tell me why my code is not showing nested child. when i run my program then i saw it is not showing child 4 name which is child of child 3. so tell me what to change there in code which make my code to show any depth of child. here i post a new thread please see and give your suggestion like what to change https://stackoverflow.com/questions/49432485/asp-net-mvc-recursive-approach-not-showing-nested-child?noredirect=1#comment85870409_49432485 – Mist Mar 22 '18 at 20:58
  • Because you query only gets the top level elements and their direct children (one level down). I will add an answer to show how to do it correctly in 30 min or so. –  Mar 22 '18 at 21:02
  • @StephenMuecke thank you sir....will be waiting for your answer. please give the code which would work for any kind of nesting means nth child or many depth. – Mist Mar 22 '18 at 21:05

1 Answers1

0

Here i like to post full working code.

@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);
}

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();
}

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; }
}
Mist
  • 684
  • 9
  • 30