Отображение дерева (tree view) с помощью ASP.NET MVC Framework
Дерево (tree view) – это прекрасный метод отображения вложенных и древовидных структур данных. Например:
![]()
Создадим HTML helper, который будет предствлять древовидную структуру, как вложенный неупорядоченный HTML список. Начнем с интерфейса для представления узла дерева. Этот интерфейс назовем IComposite, в соответсвии с шаболоном проектирования компановщик.
public interface IComposite<T>
{
T Parent { get; }
ISet<T> Children { get; }
}
Теперь убедимся, что наша сущность реализует этот интерфейс на простом примере:
public class CompositeThing : IComposite<CompositeThing>
{
public CompositeThing()
{
Children = newHashedSet<CompositeThing>();
}
public string Name { get; set; }
public CompositeThing Parent { get; set; }
public ISet<CompositeThing> Children { get; set; }
}
Теперь нам необходимо получить граф объекта из базы данных. Как это сделать, может являться темой для отдельной статьи, но наиболее приятный и простой путь это использование LINQ-to-SQL и NHibernate. И так, получив данные, можно передать их для последующего отображения:
<%= Html.RenderTree(ViewData.Model.CompositeThings, thing => thing.Name) %>
Код метода RenderTree, расширяющего HtmlHelper:
public static class TreeRenderHtmlHelper
{
public static string RenderTree<T>(
this HtmlHelper htmlHelper,
IEnumerable<T> rootLocations,
Func<T> locationRenderer)
where T : IComposite<T>
{
return new TreeRenderer<T>(rootLocations, locationRenderer).Render();
}
}
public class TreeRenderer<T> where T : IComposite<T>
{
private readonly Func<T, string> locationRenderer;
private readonly IEnumerable<T> rootLocations;
private HtmlTextWriter writer;
public TreeRenderer(
IEnumerable<T> rootLocations,
Func<T, string> locationRenderer)
{
this.rootLocations = rootLocations;
this.locationRenderer = locationRenderer;
}
public string Render()
{
writer = new HtmlTextWriter(new StringWriter());
RenderLocations(rootLocations);
return writer.InnerWriter.ToString();
}
/// <summary>
/// Рекурсивный обход дерева с выводом иерархии из элементов UL/LI
/// </summary>
/// <param name="locations"></param>
private void RenderLocations(IEnumerable<T> locations)
{
if (locations == null) return;
if (locations.Count() == 0) return;
InUl(() => locations.ForEach(location => InLi(() =>
{
writer.Write(locationRenderer(location));
RenderLocations(location.Children);
})));
}
private void InUl(Action action)
{
writer.WriteLine();
writer.RenderBeginTag(HtmlTextWriterTag.Ul);
action();
writer.RenderEndTag();
writer.WriteLine();
}
private void InLi(Action action)
{
writer.RenderBeginTag(HtmlTextWriterTag.Li);
action();
writer.RenderEndTag();
writer.WriteLine();
}
}
Результат работы метода в HTML выглядит так:
<html>
<head>
<title>Tree View</title>
<link href="jquery.treeview.css" rel="stylesheet" type="text/css" />
<script src="jquery-1.2.6.min.js" type="text/javascript"></script>
<script src="jquery.treeview.js" type="text/javascript"></script>
<script type="text/javascript">
$(function() {
$("#treeview ul").treeview();
});
</script>
</head>
<body style="font-family : Arial; ">
<h1>
Tree View
</h1>
<div id="treeview">
<ul>
<li>Root
<ul>
<li>First Child
<ul>
<li>First Grandchild</li>
<li>Second Grandchild</li>
</ul>
</li>
<li>Second Child
<ul>
<li>Third Grandchild</li>
<li>Fourth Grandchild</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</body>
</html>
В приведенном примере используется замечательный плагин для JQuery: jQuery.treeview для отображения свернутого дерева с кнопками для разворачивания.
Вы можете отслеживать комментарии к этой записи с помощью RSS 2.0. Вы можете оставить комментарий, или использовать trackback с вашего сайта.


Думаю, что если бы добавили комментарии в код на русском, то работу можно было бы считать завершенной.
+ ForEach – это относится к 3.5, если нет возможности использовать данный метод, то вполне можно добавить и самостоятельно.
public static class Extensions
{
public static void ForEach(this IEnumerable source, Action action)
{
foreach (var item in source)
{
action(item);
}
}
}
Спасибо, за конструктивную критику и полезное замечание!