Подтвердить что ты не робот

Рекурсия в представлении ASP.NET MVC

У меня есть вложенный объект данных для набора элементов внутри категорий. Каждая категория может содержать подкатегории, и нет предела ограничения глубины подкатегорий. (Файловая система будет иметь аналогичную структуру.) Это выглядит примерно так:

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

Я передаю список категорий в мое представление как IQueryable<category>. Я хочу вывести категории как набор блоков вложенных неупорядоченных списков (<ul>). Я мог бы вложить петли foreach, но тогда глубина подкатегорий будет ограничена количеством вложенных блоков foreach. В WinForms я выполнил аналогичную обработку с использованием рекурсии для заполнения TreeView, но я не видел примеров использования рекурсии в представлении ASPX MVC.

Можно ли выполнить рекурсию в представлении ASPX? Существуют ли другие механизмы просмотра, которые включают рекурсию для вывода вида?

4b9b3361

Ответ 1

Создайте собственный метод расширения 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;
        }
    }
}

Забавно, что вы должны спросить, потому что я фактически создал один из них только вчера.

Ответ 2

Вы можете легко сделать это, указав каждый <ul> список в PartialView, и для каждого нового списка вам нужно просто вызвать Html.RenderPartial("myPartialName");.

Итак, PartialView Category может выглядеть так:

<%@ 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>
<% } %>

В вашем представлении вы просто отправляете коллекцию "root" в качестве модели для частичного представления:

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

EDIT:

  • Я забыл второй параметр для вызова Html.RenderPartial() - конечно, категория должна быть передана как модель.
  • Конечно, вы правы в ошибке DRY, которую я сделал - я обновил свой код соответственно.

Ответ 3

Вы можете использовать вспомогательные методы.

@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>

Дополнительную информацию можно найти по этой ссылке: http://weblogs.asp.net/scottgu/archive/2011/05/12/asp-net-mvc-3-and-the-helper-syntax-within-razor.aspx

Ответ 4

Вы можете повторно использовать html-части с lambdas

Пример


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); %>