83

Okay, so I want to display a list containing lists of lists of lists...

I have no way of knowing how many levels there are to display, so I figured this is where I break out the old recursive routine.

I'm having trouble with exactly how to go about this though.

This is what I have so far (in view - simplified):

@foreach(MyObject item in @Model.ListOfObjects){ 
    <div> @item.Title </div>
    //Call recursive function?
}

Now each of these objects also have a List<MyObject>. I want to display each level below this div, with a tab indent per level for instance.

I was thinking a Razor function would be the thing to do here, but I need some help in forming it. Here's my thinking:

@functions{
    public static void ShowSubItems(MyObject _object){
         if(_object.ListOfObjects.Count>0){
             foreach(MyObject subItem in _object.listOfObjects){

                 // Show subItem in HTML
                 ShowSubItems(subItem);
             }
         }
     }
 }

But as you can see, I plainly need some help :)

0

3 Answers 3

219

The Razor view engine allows to write inline recursive helpers with the @helper keyword.

@helper ShowTree(IEnumerable<Foo> foos)
{
    <ul>
        @foreach (var foo in foos)
        {
            <li>
                @foo.Title
                @if (foo.Children.Any())
                {
                    @ShowTree(foo.Children)
                }
            </li>
        }
    </ul>
}
Sign up to request clarification or add additional context in comments.

7 Comments

one thing is remaining that it must call on view by @ShowTree(Foos)
This works really well. Also may make sense to mention stackoverflow.com/questions/12943245/… for referencing local variables on the cshtml page.
how can be implemented this code in asp.net core 2? in asp.net core 2, there is no @helper
@Jahan Looks like @helpers are gone in ASP.NET Core. Inline functions are one potential alternative: github.com/aspnet/Razor/issues/715#issuecomment-272890766 but look much less readable!
@PaoloMoretti When I define it as recursive Func, how can I do it? I want to create a nested comments with recursive Func. This error shows in VS2018 IDE: "Use of unassigned local variable 'FunctionName' local variable 'FunctionName' might not be initialized before accessing"
|
13

I think it is best to create an HTML helper for this. Something like this:

public static string ShowSubItems(this HtmlHelper helper, MyObject _object)
{
     StringBuilder output = new StringBuilder();
     if(_object.ListOfObjects.Count > 0)
     {
         output.Append("<ul>");

         foreach(MyObject subItem in _object.listOfObjects)
         {
             output.Append("<li>");
             output.Append(_object.Title);
             output.Append(html.ShowSubItems(subItem.listOfObjects);
             output.Append("</li>")
         }
         output.Append("</ul>");
     }
     return output.ToString();
}

Then call it like this:

@foreach(MyObject item in @Model.ListOfObjects){
    <div> @item.Title </div>
    @html.ShowSubItems(item)
}

Comments

5

In .Net core Instead of helper tag we have to use @functions. This below code might useful to some people. Here "IssuerData" is my custom object

@{
      ShowTreeData(Model.HierarchyList);
}

    @functions{

  public static void ShowTreeData(IList<IssuerData> issuers)
      {
       <ul>
      @foreach (var i in issuers)
           {
           <li>
            @i.IssuerName
             @if (i.Children.Any())
               {
                 ShowTreeData(i.Children);
               }
            </li>
          }
       </ul>
       }
   }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.