2009-06-02 14 views
23

मेरे पास श्रेणियों के भीतर वस्तुओं के एक सेट के लिए एक नेस्टेड डेटा ऑब्जेक्ट है। प्रत्येक श्रेणी में उप श्रेणियां हो सकती हैं और उप श्रेणियों की गहराई के लिए कोई निर्धारित सीमा नहीं है। (फाइल सिस्टम एक समान संरचना के लिए होगा।) यह इस तरह दिखता है:एएसपी.नेट एमवीसी व्यू में रिकर्सन

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>) ब्लॉक के सेट के रूप में आउटपुट करना चाहता हूं। मैं घोंसला फोरच लूप्स कर सकता था, लेकिन फिर उप श्रेणियों की गहराई नेस्टेड फोरैच ब्लॉक की संख्या से सीमित होगी। WinForms में, मैंने TreeView को पॉप्युलेट करने के लिए रिकर्सन का उपयोग करके समान प्रसंस्करण किया है, लेकिन मैंने एएसपीएक्स एमवीसी व्यू के भीतर रिकर्सन का उपयोग करने के किसी भी उदाहरण को नहीं देखा है।

एएसपीएक्स व्यू के भीतर रिकर्सन किया जा सकता है? क्या ऐसे अन्य व्यू इंजन हैं जिनमें व्यू आउटपुट के लिए रिकर्सन शामिल है?

+1

जब मैं इस सवाल ने लिखा है, मुझे नहीं लगता कि मैं 'IQueryable' और' IEnumerable' के बीच अंतर को समझा। मैं अब 'IENumerable' का उपयोग करूंगा क्योंकि दृश्य कोई प्रश्न नहीं कर रहा है और केवल डेटा को समझा जाना चाहिए। – CoderDennis

उत्तर

33

इसलिए की तरह अपने खुद के 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; 
     } 
    } 
} 

अजीब बात है आप क्योंकि मैं वास्तव में सिर्फ कल इनमें से किसी एक के लिए बनाया से पूछना चाहिए।

+0

मुझे यह कोड पसंद है।इस तरह के एक विशेष सहायक समारोह लिखने के लिए अजीब लगता है, लेकिन क्या यह टॉमस के जवाब में रिकर्सिव आंशिक दृश्य से बेहतर प्रदर्शन करेगा? – CoderDennis

+1

मैं 99% निश्चित हूं कि प्रदर्शन यहां बेहतर होगा। 'रेंडरपार्टियल' में कुछ ओवरहेड है जहां एक साधारण सहायक विधि के रूप में आपके पास जितना छोटा हो सकता है उतना ऊंचा हो सकता है। – Charlino

+5

यह भी एक अच्छा समाधान है - हालांकि, मैं HTML उत्पन्न करने के लिए टैगबिल्डर वर्ग का उपयोग करता हूं। या कम से कम, एक स्ट्रिंगबिल्डर, केवल तारों को संयोजित करने के बजाय ...;) –

25

आप आसानी से <ul> सूची PartialView में रखते हुए आसानी से कर सकते हैं, और प्रत्येक नई सूची के लिए आपको केवल Html.RenderPartial("myPartialName"); पर कॉल करने की आवश्यकता है।

तो Category PartialView ऐसा दिखाई दे सकता:

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

संपादित करें:

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

आपके विचार में, आप बस आंशिक दृश्य के लिए मॉडल के रूप में "रूट" संग्रह भेज

  • मैं Html.RenderPartial() कॉल पर दूसरा पैरामीटर भूल गया था - निश्चित रूप से श्रेणी एच मॉडल के रूप में पारित किया जाना है।
  • बेशक आप मेरे द्वारा बनाई गई डीआरवाई गलती के बारे में सही हैं - मैंने तदनुसार अपना कोड अपडेट किया है।
+0

आंशिक दृश्य के अंदर, यह उप श्रेणी आंशिक दृश्य के मॉडल के रूप में cat.categories को कैसे सेट कर रहा है? – CoderDennis

+0

रेंडरपार्टियल विधि मॉडल के रूप में उपयोग करने के लिए दूसरा पैरामीटर ले सकता है। निजी तौर पर मैं आपके पेज पर लूप नहीं करता, बस इसे अपने श्रेणी संग्रह को पास करता हूं और वहां लूपिंग शुरू करता हूं - यह उस तरह से अधिक ड्रवाई है। – Charlino

6

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

यह एक बहुत अच्छा समाधान है। एक दिलचस्प वैकल्पिक दृष्टिकोण के लिए –

18

आप सहायक तरीकों का उपयोग कर सकते हैं के साथ एचटीएमएल भागों का पुन: उपयोग कर सकते हैं।

@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

+1 के बारे में अच्छी तरह से सोचा। मैंने अभी तक यह नहीं देखा था। – CoderDennis

संबंधित मुद्दे