Отображение дерева (tree view) с помощью ASP.NET MVC Framework

Перевод статьи:Rendering a tree view using the 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 для отображения свернутого дерева с кнопками для разворачивания.

Like it? Tweet it!

Вы можете отслеживать комментарии к этой записи с помощью RSS 2.0. Вы можете оставить комментарий, или использовать trackback с вашего сайта.

Комментарии: 2 »

 
  • Павел:

    Думаю, что если бы добавили комментарии в код на русском, то работу можно было бы считать завершенной.
    + ForEach – это относится к 3.5, если нет возможности использовать данный метод, то вполне можно добавить и самостоятельно.


    public static class Extensions
    {
    public static void ForEach(this IEnumerable source, Action action)
    {
    foreach (var item in source)
    {
    action(item);
    }
    }
    }

  • Спасибо, за конструктивную критику и полезное замечание!

 

Добавить комментарий

XHTML: Можно использовать эти теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>