2009-06-02 14 views
23

Kategorilerdeki öğeler kümesi için iç içe geçmiş veri nesnesine sahibim. Her kategori alt kategoriler içerebilir ve alt kategorilerin derinliği için belirlenmiş bir sınır yoktur. (Bir dosya sistemi benzer bir yapıya sahip olacaktır.) Bu şuna benzer:Bir ASP.NET MVC görünümünde 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; 
} 

Ben IQueryable<category> olarak benim görünümüne kategori listesi geçirerek. Kategorileri bir dizi iç içe sıralanmamış liste (<ul>) bloğu olarak çıkarmak istiyorum. Foreach döngülerine yuva yapabilirim, ancak alt kategorilerin derinliği, iç içe geçmiş foreach bloklarının sayısıyla sınırlanabilir. WinForms'de, bir TreeView doldurmak için özyineleme kullanarak benzer işlem yaptım, ancak bir ASPX MVC görünümünde yineleme kullanma örnekleri görmedim.

Özyineleme bir ASPX görünümünde yapılabilir mi? Görünüm çıkışı için tekrarlama içeren başka görüş motorları var mı?

+1

, ben IQueryable' ve 'IEnumerable'' arasındaki farkı anladığını sanmıyorum. Görünüm hiçbir sorgulama yapmadığından ve yalnızca veriyi sayması gerektiğinden, artık IEnumerable kullanıyorum. – CoderDennis

cevap

33

böylece gibi kendi HtmlHelper uzantısı yöntemi oluşturun: Aslında sadece dün bunlardan birini oluşturdu çünkü

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; 
     } 
    } 
} 

Komik sormalısınız.

+0

Bu kodu beğendim.Böyle bir uzman yardımcısı işlevi yazmak garip görünüyor, ama bu Tomas'ın cevabındaki tekrarlayıcı kısmi görüşten daha iyi performans gösterecek mi? – CoderDennis

+1

Burada% 99 performansın daha iyi olacağına eminim. 'RenderPartial', basit bir yardımcı metodun sahip olabileceğiniz kadar az masrafa sahip olduğu bazı ek yüklere sahiptir. – Charlino

+5

Bu da iyi bir çözüm - ancak HTML oluşturmak için TagBuilder sınıfını kullanırdım. Ya da en azından, bir StringBuilder, sadece dizeleri birleştirmek yerine ...;) –

25

PartialView numaralı telefondan her bir <ul> listesine sahip olmakla kolayca başlayabilirsiniz ve her yeni listeye başlamak için yalnızca Html.RenderPartial("myPartialName"); numaralı telefonu arayın.

Yani Category PartialView bu gibi görünebilir:

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

DÜZENLEME:

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

senin Görünüm olarak, sadece kısmi görünümü için model olarak "kök" koleksiyonu göndermek

  • İkinci parametreyi Html.RenderPartial() numaralı aramayı unuttum. model olarak geçecek.
  • Tabii ki yaptığım DRY hatası hakkında haklısınız - Kodumu buna göre güncelledim.
+0

Kısmi görünümde, cat.categories alt kategori kısmi görünümü için model olarak nasıl ayarlanır? – CoderDennis

+0

RenderPartial yöntemi, model olarak kullanılacak ikinci bir parametre alabilir. Şahsen sayfanızda döngü yapmazdım, sadece kategori koleksiyonunuzu geçirir ve oradaki döngüyü başlatır - bu şekilde daha fazla KURU. – Charlino

6

Sen lambdas

Örnek


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

BU, çok daha güzel bir çözümdür. ilginç bir alternatif yaklaşım için –

18

Sen yardımcı yöntemlerini kullanabilirsiniz html parçaları yeniden kullanabilirsiniz.

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

diğer bilgiler bu bağlantıyı bulunabilir: Bu soruyu yazdığımda http://weblogs.asp.net/scottgu/archive/2011/05/12/asp-net-mvc-3-and-the-helper-syntax-within-razor.aspx

+4

+ 1 iyi düşünülmüş. Onu henüz görmedim. – CoderDennis