HtmlHelper extension: HierarchicalRenderer
July 16th, 2008
I want to share with you an HtmlHelper extension method that I created to render a tree. It takes advantage of lamda expressions, so you can feel more comfortable when using it. It is not binded to any interface or class for the node type.
How using it looks like
For this example, I use as node class a type NodeViewData that holds some properties such as a string Caption, a Guid Id, and a List<NodeViewData>Children.
We will construct a simple tree, from a list of NodeViewData. This tree will be indented according to the depth, and with some simple Javascript we will show a message with its Id when clicking it.
<%= Html.HierarchicalRender<NodeViewData> ( // We pass an instance of IEnumerable<NodeViewData> // so it can iterate over the root nodes this.ViewData.Model.RootNodes, // We will use a <br /> as separator between nodes “<br />”, // I recieve an HierarchyInformation<NodeViewData> instance // it contains the Node, the parents of the node, // and the node order in its trunk // You specify a delegate (lamda) that returns // the HTML for the node being processed h => string.Format( // This is the basic node format I will use for the sample “<a href=\”#\” style=\”margin-left: {0}px\” onclick=\”alert (’{2}’); return false\”>{1}</a>”, // I will multiply the node parents count (depth) to indent the node h.ReversedParents.Length * 20, // We render the HTML for the caption Html.Encode (h.Node.Caption), // Let’s show the node Id when clicking h.Node.Id), // For a given node (n) let’s pass an expression // to return a IEnumerable of the same type // this expression will be used to let the // HierarchicalRendered iterate over its children n => n.Children) %>
Get it!
You can download a sample solution from http://cid-9e5d4c3be8afbb19.skydrive.live.com/self.aspx/Posts/SampleMvc.zip
In the HierarchicalRender.cs you can find the HtmlHelper extension method and classes.
Remember to have the namespace of the extension method in your markup to use it!
Glue code
Below I put the HierarchicalRender class (extension method) and the HierarchyInformation class (used for node the nodeFormat delegate).
public static string HierarchicalRender<T>( this HtmlHelper helper, IEnumerable<T> source, string nodeSeparator, Expression<Func<HierarchyInformation<T>, string>> nodeFormat, Expression<Func<T, IEnumerable<T>>> childEnumerator) { var builder = new StringBuilder(); HierarchicalRender<T>( helper, source, nodeSeparator, nodeFormat.Compile(), childEnumerator.Compile(), new T[0], builder); return builder.ToString(); } private static void HierarchicalRender<T>( this HtmlHelper helper, IEnumerable<T> source, string nodeSeparator, Func<HierarchyInformation<T>, string> nodeFormat, Func<T, IEnumerable<T>> childEnumerator, T[] reversedParents, StringBuilder builder) { int order = 0; foreach (T node in source) { if (order > 0) builder.Append(nodeSeparator); var info = new HierarchyInformation<T> { Node = node, Order = order, ReversedParents = reversedParents }; builder.Append(nodeFormat.Invoke(info)); var children = childEnumerator.Invoke(node).ToList(); if (children.Count > 0) { builder.Append(nodeSeparator); var reversedParentsWithSelf = reversedParents.ToList(); reversedParentsWithSelf.Insert(0, node); HierarchicalRender<T>( helper, children, nodeSeparator, nodeFormat, childEnumerator, reversedParentsWithSelf.ToArray(), builder); } order++; } } public class HierarchyInformation<T> { public T Node { get; set; } public T[] ReversedParents { get; set; } public int Order { get; set; } }
Leave a Reply
You must be logged in to post a comment.