Recursion in an ASP.NET MVC view

后端 未结 4 1031
后悔当初
后悔当初 2020-12-01 03:58

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

相关标签:
4条回答
  • 2020-12-01 04:20

    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.

    0 讨论(0)
  • 2020-12-01 04:30

    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.
    0 讨论(0)
  • 2020-12-01 04:30

    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

    0 讨论(0)
  • 2020-12-01 04:31

    You can reuse html parts with lambdas

    Example

    
    public class Category
        {
            public int id;
            public string name;
            public IEnumerable categories;
        }
    
     <%
            Action<IEnumerable<Category>> categoriesMacros = null;
            categoriesMacros = categories => { %>
            <ul>
                <% foreach(var c in categories) { %>
                    <li> <%= Html.Encode(c.name)%> </li>
                    <% if (c.categories != null && c.categories.Count() > 0) categoriesMacros(c.categories);  %>
                <% } %>
            </ul>
            <% }; %>
    
        <% var categpries = (IEnumerable<Category>)ViewData["categories"]; %>
        <% categoriesMacros(categpries); %>
    
    0 讨论(0)
提交回复
热议问题