Created
December 27, 2011 17:31
-
-
Save thunklife/1524481 to your computer and use it in GitHub Desktop.
MVC Tree View alternative using ExpressionBuilder objects
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public static class FluentTreeViewHelper | |
| { | |
| /// <summary> | |
| /// Create an HTML tree from a recursive collection of items | |
| /// </summary> | |
| public static FluentTreeView<T> FluentTreeView<T>(this HtmlHelper html, IEnumerable<T> items) | |
| { | |
| return new FluentTreeView<T>(html, items); | |
| } | |
| } | |
| public class FluentTreeView<T> : IHtmlString | |
| { | |
| private readonly HtmlHelper _html; | |
| private readonly IEnumerable<T> _items = Enumerable.Empty<T>(); | |
| internal Func<T, string> DisplayProperty = item => item.ToString(); | |
| internal Func<T, IEnumerable<T>> ChildrenProperty; | |
| private string _emptyContent = "No children"; | |
| internal IDictionary<string, object> HtmlAttributes = new Dictionary<string, object>(); | |
| internal IDictionary<string, object> ChildHtmlAttributes = new Dictionary<string, object>(); | |
| internal Func<T, HelperResult> ItemTemplate; | |
| public FluentTreeView(HtmlHelper html, IEnumerable<T> items) | |
| { | |
| if (html == null) throw new ArgumentNullException("html"); | |
| _html = html; | |
| _items = items; | |
| // The ItemTemplate will default to rendering the DisplayProperty | |
| ItemTemplate = item => new HelperResult(writer => writer.Write(DisplayProperty(item))); | |
| } | |
| public ChildItemsExpression<T> EmptyContent(string emptyContent) | |
| { | |
| if (emptyContent == null) throw new ArgumentNullException("emptyContent"); | |
| _emptyContent = emptyContent; | |
| return new ChildItemsExpression<T>(this); | |
| } | |
| public override string ToString() | |
| { | |
| ValidateSettings(); | |
| var listItems = _items.ToList(); | |
| var ul = new TagBuilder("ul"); | |
| ul.MergeAttributes(HtmlAttributes); | |
| if (listItems.Count() == 0) | |
| { | |
| var li = new TagBuilder("li") | |
| { | |
| InnerHtml = _emptyContent | |
| }; | |
| ul.InnerHtml = li.ToString(); | |
| } | |
| foreach (var item in listItems) | |
| { | |
| RenderLi(ul, item); | |
| AppendChildren(ul, item, ChildrenProperty); | |
| } | |
| return ul.ToString(); | |
| } | |
| public string ToHtmlString() | |
| { | |
| return ToString(); | |
| } | |
| public void Render() | |
| { | |
| var writer = _html.ViewContext.Writer; | |
| using (var textWriter = new HtmlTextWriter(writer)) | |
| { | |
| textWriter.Write(ToString()); | |
| } | |
| } | |
| private void ValidateSettings() | |
| { | |
| if (ChildrenProperty == null) | |
| { | |
| throw new InvalidOperationException("You must call the Children() method to tell the tree view how to find child items"); | |
| } | |
| } | |
| private void AppendChildren(TagBuilder ul, T parent, Func<T, IEnumerable<T>> childrenProperty) | |
| { | |
| var children = childrenProperty(parent).ToList(); | |
| if (children.Count() == 0) | |
| { | |
| return; | |
| } | |
| var innerUl = new TagBuilder("ul"); | |
| innerUl.MergeAttributes(ChildHtmlAttributes); | |
| foreach (T item in children) | |
| { | |
| RenderLi(innerUl, item); | |
| AppendChildren(innerUl, item, childrenProperty); | |
| } | |
| ul.InnerHtml += innerUl.ToString(); | |
| } | |
| private void RenderLi(TagBuilder ul, T item) | |
| { | |
| var li = new TagBuilder("li") | |
| { | |
| InnerHtml = ItemTemplate(item).ToHtmlString() | |
| }; | |
| ul.InnerHtml += li.ToString(); | |
| } | |
| } | |
| public class ChildItemsExpression<T> | |
| { | |
| private readonly FluentTreeView<T> _treeView; | |
| public ChildItemsExpression(FluentTreeView<T> treeView) | |
| { | |
| if (treeView != null) | |
| { | |
| _treeView = treeView; | |
| } | |
| } | |
| public ItemTemplateExpression<T> Children(Func<T, IEnumerable<T>> selector) | |
| { | |
| if (selector == null) throw new ArgumentNullException("selector"); | |
| _treeView.ChildrenProperty = selector; | |
| return new ItemTemplateExpression<T>(_treeView); | |
| } | |
| } | |
| public class ItemTemplateExpression<T> | |
| { | |
| private readonly FluentTreeView<T> _treeView; | |
| public ItemTemplateExpression(FluentTreeView<T> treeView) | |
| { | |
| if (treeView != null) | |
| { | |
| _treeView = treeView; | |
| } | |
| } | |
| public HtmlAttributeExpression<T> ItemText(Func<T, string> selector) | |
| { | |
| if (selector == null) throw new ArgumentNullException("selector"); | |
| _treeView.DisplayProperty = selector; | |
| return new HtmlAttributeExpression<T>(_treeView); | |
| } | |
| public HtmlAttributeExpression<T> ItemTemplate(Func<T, HelperResult> itemTemplate) | |
| { | |
| if (itemTemplate == null) throw new ArgumentNullException("itemTemplate"); | |
| _treeView.ItemTemplate = itemTemplate; | |
| return new HtmlAttributeExpression<T>(_treeView); | |
| } | |
| } | |
| public class HtmlAttributeExpression<T> | |
| { | |
| private readonly FluentTreeView<T> _treeView; | |
| public HtmlAttributeExpression(FluentTreeView<T> treeView) | |
| { | |
| if (treeView != null) | |
| { | |
| _treeView = treeView; | |
| } | |
| } | |
| public ChildHtmlAttributExpression<T> HtmlAttributes(object htmlAttributes) | |
| { | |
| HtmlAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); | |
| return new ChildHtmlAttributExpression<T>(_treeView); | |
| } | |
| public ChildHtmlAttributExpression<T> HtmlAttributes(IDictionary<string, object> htmlAttributes) | |
| { | |
| if (htmlAttributes == null) throw new ArgumentNullException("htmlAttributes"); | |
| _treeView.HtmlAttributes = htmlAttributes; | |
| return new ChildHtmlAttributExpression<T>(_treeView); | |
| } | |
| public ChildHtmlAttributExpression<T> WithDefaultHtmlAttributes() | |
| { | |
| return new ChildHtmlAttributExpression<T>(_treeView); | |
| } | |
| } | |
| public class ChildHtmlAttributExpression<T> | |
| { | |
| private readonly FluentTreeView<T> _treeView; | |
| public ChildHtmlAttributExpression(FluentTreeView<T> treeView) | |
| { | |
| if (treeView != null) | |
| { | |
| _treeView = treeView; | |
| } | |
| } | |
| public FluentTreeView<T> ChildHtmlAttributes(object htmlAttributes) | |
| { | |
| return ChildHtmlAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); | |
| } | |
| public FluentTreeView<T> ChildHtmlAttributes(IDictionary<string, object> htmlAttributes) | |
| { | |
| if (htmlAttributes == null) throw new ArgumentNullException("htmlAttributes"); | |
| _treeView.ChildHtmlAttributes = htmlAttributes; | |
| return _treeView; | |
| } | |
| public FluentTreeView<T> WithDefaultChildHtmlAttributes() | |
| { | |
| return _treeView; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Nice