ASP.NET MVC Repeater Help
I have built a little repeater HtmlHelper for asp.net MVC and I would like to be able to recurse through to build an tr开发者_StackOverflow社区ee style list. So if <T>
has any children that are IEnumerable
I would like to add them as embedded lists.
Here is what I have so for which creates a flat list...
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()));
}
Any help would be greatly appreciated.
Cheers in advance.
Gifster
I would approach this using recursion. I doubt if simply appending the string to content will be enough. You probably need to parse the HTML from the template and insert it into the template in an intelligent fashion depending on whether it's a list or a table, etc. I'm omitting the implementation of that method since I don't know how you expect it to be used. I am showing how to use HtmlAgilityPack, though, for the parsing.
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()));
}
精彩评论