Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursion in an ASP.NET MVC view

I have a nested data object for a set of items within categories. Each category can contain sub categories and there is no set limit to the depth of sub categories. (A file system would have a similar structure.) It looks something like this:

class category
{
    public int id;
    public string name;
    public IQueryable<category> categories;
    public IQueryable<item> items;
}
class item
{
    public int id;
    public string name;
}

I am passing a list of categories to my view as IQueryable<category>. I want to output the categories as a set of nested unordered list (<ul>) blocks. I could nest foreach loops, but then the depth of sub categories would be limited by the number of nested foreach blocks. In WinForms, I have done similar processing using recursion to populate a TreeView, but I haven't seen any examples of using recursion within an ASPX MVC view.

Can recursion be done within an ASPX view? Are there other view engines that include recursion for view output?

like image 485
CoderDennis Avatar asked Jun 02 '09 23:06

CoderDennis


3 Answers

Create your own HtmlHelper extension method like so:

namespace System.Web.Mvc
{
    public static class HtmlHelperExtensions
    {
        public static string CategoryTree(this HtmlHelper html, IEnumerable<Category> categories)
        {
            string htmlOutput = string.Empty;

            if (categories.Count() > 0)
            {
                htmlOutput += "<ul>";
                foreach (Category category in Categories)
                {
                    htmlOutput += "<li>";
                    htmlOutput += category.Name;
                    htmlOutput += html.CategoryTree(category.Categories);
                    htmlOutput += "</li>";
                }
                htmlOutput += "</ul>";
            }

            return htmlOutput;
        }
    }
}

Funny you should ask because I actually created one of these just yesterday.

like image 99
Charlino Avatar answered Nov 13 '22 06:11

Charlino


You could easily do it by having each <ul> list in a PartialView, and for each new list you need to start you just call Html.RenderPartial("myPartialName");.

So the Category PartialView could look like this:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Category>>" %>
<% foreach(Category cat in ViewData.Model) { %>
     <li><p><%= cat.name %></p>
        <% if (cat.categories.Count > 0) {
                Html.RenderPartial("Category", cat.Categories);
           } %></li>
<% } %>

In your View, you simply send the "root" collection as the model for the partial view:

<% Html.RenderPartial("Category", ViewData.Model) %>

EDIT:

  • I had forgotten the second parameter to the Html.RenderPartial() call - of course the category has to be passed as the model.
  • Of course you are right about the DRY mistake I made - I have updated my code accordingly.
like image 26
Tomas Aschan Avatar answered Nov 13 '22 05:11

Tomas Aschan


You can use helper methods.

@model Models.CategoryModel

@helper TreeView(List<Models.CategoryModel> categoryTree)
{
    foreach (var item in categoryTree)
    {
    <li>
        @if (item.HasChild)
        {
            <span>@item.CategoryName</span>
            <ul>
                @TreeView(item.ChildCategories)
            </ul>
        }
        else
        {
            <span class="leaf @item.CategoryTreeNodeType.ToString()" id="@item._CategoryId">@item.CategoryName</span> 
        }
    </li>
    }
}

<ul id="categorytree">
    <li>@Model.CategoryName
    @TreeView(Model.ChildCategories)
    </li>
</ul>

More info can be found on this link: http://weblogs.asp.net/scottgu/archive/2011/05/12/asp-net-mvc-3-and-the-helper-syntax-within-razor.aspx

like image 23
Ozan BAYRAM Avatar answered Nov 13 '22 05:11

Ozan BAYRAM