2011-02-02 4 views
0

Я создал небольшой ретранслятор HtmlHelper для asp.net MVC, и я хотел бы иметь возможность рекурсивно строить список древовидных стилей. Так что, если у <T> есть дети, которые IEnumerable Я хочу добавить их в список в виде вложений.Справка ASP.NET MVC Repeater

Вот то, что я так, для которых создает плоский список ...

public static MvcHtmlString Repeater<T>(this HtmlHelper html, IEnumerable<T> items, 
     Func<T, HelperResult> itemTemplate,    
     Func<string, HelperResult> containerTemplate, 
     Func<string, HelperResult> emptyTemplate) 
    { 
     if (items == null) 
      return MvcHtmlString.Create(HttpContext.Current.Server.HtmlDecode(emptyTemplate("No Results").ToHtmlString())); 

     if (items.Count() == 0) 
      return MvcHtmlString.Create(HttpContext.Current.Server.HtmlDecode(emptyTemplate("No Results").ToHtmlString())); 

     StringBuilder sb = new StringBuilder(); 

     foreach (var item in items) 
     { 
      string content = itemTemplate(item).ToHtmlString(); 

      //Here I would want to append the children to 'content' using containerTemplate and itemTemplate.... 

      sb.Append(HttpContext.Current.Server.HtmlDecode(content)); 
     } 

     return MvcHtmlString.Create(HttpContext.Current.Server.HtmlDecode(containerTemplate(sb.ToString()).ToHtmlString())); 
    } 

Любая помощь будет принята с благодарностью.

Приветствия заранее.

Gifster

ответ

1

Я бы подошел к этому, используя рекурсию. Я сомневаюсь, что достаточно просто добавить строку к контенту. Вероятно, вам нужно проанализировать HTML-код из шаблона и вставить его в шаблон в интеллектуальном режиме в зависимости от того, является ли это списком или таблицей и т. Д. Я опускаю реализацию этого метода, так как я не знаю, как вы ожидаете он будет использоваться. Я показываю, как использовать HtmlAgilityPack, хотя для синтаксического анализа.

using HtmlAgilityPack; 

public static MvcHtmlString Repeater<T>(this HtmlHelper html, IEnumerable<T> items, 
    Func<T, HelperResult> itemTemplate,    
    Func<string, HelperResult> containerTemplate, 
    Func<string, HelperResult> emptyTemplate) 
{ 
    if (items == null) 
     return MvcHtmlString.Create(HttpContext.Current.Server.HtmlDecode(emptyTemplate("No Results").ToHtmlString())); 

    if (items.Count() == 0) 
     return MvcHtmlString.Create(HttpContext.Current.Server.HtmlDecode(emptyTemplate("No Results").ToHtmlString())); 

    StringBuilder sb = new StringBuilder(); 

    var enumerableProperties = typeof(T).GetProperties() 
             .Where(p => p is IEnumerable); 

    foreach (var item in items) 
    { 
     var doc = new HtmlDocument(); 
     doc.LoadHtml(itemTemplate(item).ToHtmlString()); 
     var root = doc.DocumentNode.FirstChild; 
     var insertNode = FindInsertNode(doc); // this needs to be written   
     foreach (var property in enumerableProperties) 
     { 
      var value = property.GetValue(item, null) as IEnumerable; 
      var newNode = new HtmlNode 
          { 
           InnerHtml = html.Repeater(value, itemTemplate, containerTemplate, emptyTemplate) 
          }; 
      root.InsertAfter(newNode, insertNode); 
      insertNode = newNode; 
     } 
     sb.Append(html.InnerText); 
    } 

    return MvcHtmlString.Create(HttpContext.Current.Server.HtmlDecode(containerTemplate(sb.ToString()).ToHtmlString())); 
} 
+0

Спасибо, но это будет либо IEnumerable дети T, но я думаю, что я буду иметь идти с сильно типизированных версий этого повторителя ... – Andy

+1

@Andy - извините, я не понял. Вы можете использовать отражение для перечисления свойств объекта, чтобы найти те, которые являются IEnumerable. Я обновлю. – tvanfosson

+0

Знаете ли вы пример? – Andy