ASP.NET MVC视图中的递归

Cod*_*nis 25 asp.net-mvc recursion

我有一个嵌套的数据对象,用于类别中的一组项目.每个类别都可以包含子类别,子类别的深度没有设置限制.(文件系统将具有类似的结构.)它看起来像这样:

class category
{
    public int id;
    public string name;
    public IQueryable<category> categories;
    public IQueryable<item> items;
}
class item
{
    public int id;
    public string name;
}
Run Code Online (Sandbox Code Playgroud)

我将一个类别列表传递给我的视图IQueryable<category>.我想将类别输出为一组嵌套的无序列表(<ul>)块.我可以嵌套foreach循环,但子类别的深度将受到嵌套foreach块数量的限制.在WinForms中,我使用递归来完成类似的处理来填充a TreeView,但我还没有看到在ASPX MVC视图中使用递归的任何示例.

可以在ASPX视图中完成递归吗?是否有其他视图引擎包含视图输出的递归?

Cha*_*ino 34

像这样创建自己的HtmlHelper扩展方法:

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

有趣的是你应该问,因为我实际上昨天创造了其中一个.

  • 这也是一个很好的解决方案 - 但是,我会使用TagBuilder类来生成HTML.或者至少是一个StringBuilder,而不是仅仅连接字符串...;) (5认同)
  • 将所有html放在一行上有什么问题?浏览器不关心缩进.除了IE6之外,如果你对IE6 + LI标签+ CSS有所了解,那么最好将它们全部捆绑起来.但是,如果你担心它,请投入一些换行等.你可能想阅读Rob Conery的'避免标签汤'博客文章,他按照"如果有一个IF,让它成为帮手"的规则生活.此外,MSDN文章"您的ASP.NET MVC应用程序的指导原则",因为它有一个关于HTML帮助程序的好的部分. (5认同)

Tom*_*han 26

您可以通过将每个<ul>列表放在a中轻松完成PartialView,并且对于每个新列表,您只需要启动即可Html.RenderPartial("myPartialName");.

所以CategoryPartialView看起来像这样:

<%@ 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>
<% } %>
Run Code Online (Sandbox Code Playgroud)

在View中,您只需发送"root"集合作为局部视图的模型:

<% Html.RenderPartial("Category", ViewData.Model) %>
Run Code Online (Sandbox Code Playgroud)

编辑:

  • 我忘记了Html.RenderPartial()调用的第二个参数- 当然必须将类别作为模型传递.
  • 当然你对我犯的干错是对的 - 我已经相应更新了我的代码.


Oza*_*RAM 23

您可以使用辅助方法.

@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>
Run Code Online (Sandbox Code Playgroud)

更多信息可以在以下链接中找到:http: //weblogs.asp.net/scottgu/archive/2011/05/12/asp-net-mvc-3-and-the-helper-syntax-within-razor.aspx

  • +1是一个有趣的替代方法.我还没见过. (4认同)

Nai*_*nov 6

您可以使用lambdas重用html部分


public class Category
    {
        public int id;
        public string name;
        public IEnumerable categories;
    }
Run Code Online (Sandbox Code Playgroud)
 <%
        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); %>
Run Code Online (Sandbox Code Playgroud)