ASP.NET MVC中继器帮助

时间:2011-02-02 17:37:32

标签: c# asp.net-mvc recursion

我已经为asp.net MVC构建了一个小的转发器HtmlHelper,我希望能够通过递归来构建一个树样式列表。因此,如果<T>有任何IEnumerable子项,我想将它们添加为嵌入列表。

这就是我所拥有的,它创建了一个平面列表......

    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 个答案:

答案 0 :(得分: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()));
}