Asp.net mvc ASP.NET MVC视图中的递归

Asp.net mvc ASP.NET MVC视图中的递归,asp.net-mvc,recursion,Asp.net Mvc,Recursion,我有一个嵌套的数据对象,用于类别中的一组项。每个类别都可以包含子类别,子类别的深度没有设置限制。(文件系统将具有类似的结构。)它看起来像这样: class category { public int id; public string name; public IQueryable<category> categories; public IQueryable<item> items; } class item { public i

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

class category
{
    public int id;
    public string name;
    public IQueryable<category> categories;
    public IQueryable<item> items;
}
class item
{
    public int id;
    public string name;
}
<%@ 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>
<% } %>
类别
{
公共int id;
公共字符串名称;
公共可查询类别;
公共物品;
}
类项目
{
公共int id;
公共字符串名称;
}
我将类别列表作为
IQueryable
传递给我的视图。我想将类别输出为一组嵌套的无序列表(
)块。我可以嵌套foreach循环,但子类别的深度将受到嵌套foreach块数量的限制。在WinForms中,我使用递归来填充
TreeView
,做了类似的处理,但我没有看到在ASPX MVC视图中使用递归的任何示例


可以在ASPX视图中执行递归吗?是否还有其他视图引擎包含用于视图输出的递归?

您可以通过将每个
列表放在
PartialView
中轻松实现,对于每个新列表,您只需调用
Html.RenderPartial(“myPartialName”)

因此,
Category
PartialView可以如下所示:

class category
{
    public int id;
    public string name;
    public IQueryable<category> categories;
    public IQueryable<item> items;
}
class item
{
    public int id;
    public string name;
}
<%@ 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>
<% } %>

  • 0) { Html.RenderPartial(“类别”,类别); }%%>
  • 在您的视图中,只需发送“根”集合作为局部视图的模型:

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

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

    创建自己的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;
            }
        }
    }
    
    namespace System.Web.Mvc
    {
    公共静态类HtmlHelperExtensions
    {
    公共静态字符串类别树(此HtmlHelper html,IEnumerable categories)
    {
    string htmlOutput=string.Empty;
    如果(categories.Count()>0)
    {
    htmlOutput+=“
      ”; foreach(类别中的类别) { htmlOutput+=“
    • ”; htmlOutput+=category.Name; htmlOutput+=html.CategoryTree(category.Categories); htmlOutput+=“
    • ”; } htmlOutput+=“
    ”; } 返回htmlOutput; } } }

    有趣的是,你应该问,因为我昨天才创建了其中的一个。

    你可以在lambdas中重用html部件

    范例

    
    public class Category
        {
            public int id;
            public string name;
            public IEnumerable categories;
        }
    
    {%>
    
    • 0)分类宏(c.分类);%%>

    您可以使用助手方法

    @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>
    
    @model Models.CategoryModel
    @助手树视图(列表类别树)
    {
    foreach(类别树中的var项)
    {
    
  • @if(项目HasChild) { @item.CategoryName
      @TreeView(项目.子类别)
    } 其他的 { @item.CategoryName }
  • } }
    • @Model.CategoryName @TreeView(Model.ChildCategories)
    可在此链接上找到更多信息:

    在部分视图中,如何将cat.categories设置为子类别部分视图的模型?RenderPartial方法可以使用第二个参数作为其模型。就个人而言,我不会在您的页面上进行循环,只需将您的类别集合传递给它,然后在那里开始循环-这样更干燥。我喜欢这段代码。Se写这样一个专门的助手函数很奇怪,但是这会比Tomas的答案中的递归局部视图更好吗?我99%肯定这里的性能会更好。“RenderPartial”有一些开销,而作为一个简单的助手方法,开销尽可能少。这也是一个很好的解决方案-但是,我会使用TagBuilder类来生成HTML。或者至少是一个StringBuilder,而不仅仅是串接字符串…;)这种方法的问题是所有HTML都在一行上。如果您尝试有多行,则标识会出错。因此,对于这样大量的数据,PartialView更好。我认为HtmlHelper扩展方法应该用于单个标记,就像它们在框架中使用一样。将所有html放在一行有什么错?浏览器不关心缩进。除了IE6之外,如果你知道IE6+LI标记+CSS,最好将它们都聚在一起。但是如果你担心这一点,可以添加一些换行符等。你可能不想这样做o阅读Rob Conry的“避免标签汤”博文,他遵循“如果有If,让它成为帮助者”的原则。此外,还有MSDN文章“ASP.NET MVC应用程序的指导原则”因为它有一个关于HTML助手的很好的部分。这是一个更好的解决方案。我们考虑了+1作为一个有趣的替代方法。我还没有看到。当我写这个问题时,我认为我不理解
    IQueryable
    IEnumerable
    之间的区别。我现在会使用
    IEnumerable
    ,因为视图不起作用任何查询和都应仅枚举数据。