Возможности:
- Отображение списка
- Добавление элементов
- Перемещение элементов
- Удаление элементов
Используемые технологии:
- Microsoft ASP. NET MVC 4
- Entity Framework
- Linq to Entity
- Microsoft SQL Server (Local DB)
База данных
Так как все записи будут храниться в базе данных, то необходимо создать следующую таблицу:
public class News { public int Id {get;set;} //Идентификатор новости public int? ParentId {get;set;} //Идентификатор родительской новости public string Title {get;set;} //Заголовок новости public bool IsDeleted {get;set;} //Флаг удаления }
Модели
Далее создадим модели для работы:
1. Обычно в моделях не используют напрямую записи из базы данных, поэтому создадим модель похожую на таблицу.
public class NewsModel { public int Id {get;set;} //Идентификатор новости public int? ParentId {get;set;} //Идентификатор родительской новости public string Title {get;set;} //Заголовок новости }
2. Список новостей.
public NewsListModel { public int? Seed {get;set;} //Корневой элемент public IEnumerable<NewsModel> News {get;set;} //Список новостей }
Контроллер
Ниже представлен контроллер, который умеет выбирать, удалять, добавлять и перемещать новости.
public class NewsController : Controller { public ActionResult Index() { using (NewsContext context = new NewsContext()) { NewsListModel model = new NewsListModel() { News = context.News.Where(x => !x.IsDeleted).ToArray().Select(x => new NewsModel(x)) }; return View(model); } } [HttpPost] [ValidateAntiForgeryToken] public ActionResult Add(int? parentId, string title) { using (NewsContext context = new NewsContext()) { var newNews = new News() { ParentId = parentId, Title = title }; context.News.Add(newNews); context.SaveChanges(); } return RedirectToAction("Index"); } [ValidateAntiForgeryToken] [HttpPost] public ActionResult Move(int nodeId, int? newParentId) { if (nodeId == newParentId) { return RedirectToAction("Index"); } using (NewsContext context = new NewsContext()) { if (newParentId.HasValue && ContainsChilds(context, nodeId, newParentId.Value)) { return RedirectToAction("Index"); } var node = context.News.Where(x => x.Id == nodeId).Single(); node.ParentId = newParentId; context.SaveChanges(); } return RedirectToAction("Index"); } private bool ContainsChilds(NewsContext context, int parentId, int id) { bool result = false; var inner = context.News.Where(x => x.ParentId == parentId && !x.IsDeleted).ToArray(); foreach (var node in inner) { if (node.Id == id && node.ParentId == parentId) { return true; } result = ContainsChilds(context, node.Id, id); } return result; } [HttpPost] public ActionResult Delete(int id) { using (NewsContext context = new NewsContext()) { DeleteNodes(context, id); context.SaveChanges(); } return RedirectToAction("Index"); } private void DeleteNodes(NewsContext context, int id) { var inner = context.News.Where(x => x.ParentId == id && !x.IsDeleted).ToArray(); foreach (var node in inner) { node.IsDeleted = true; DeleteNodes(context, node.Id); } var deleted = context.News.Where(x => x.Id == id && !x.IsDeleted).Single(); deleted.IsDeleted = true; } }
Представление
Как видно из кода, большинство методов выполняются рекурсивно. Рекурсия позволяет достаточно лаконично реализовать операции. Так же рекурсия используется при отображении на странице. Рассмотрим вывод древовидного списка.
_TreeList.cshtml
@model MySLOTree.Models.NewsListModel @if (Model.News.Where(x => x.ParentId == Model.Seed).Any()) { <ul> @foreach (var node in Model.News) { if (node.ParentId == Model.Seed) { <a>@node.Title</a> MySLOTree.Models.NewsListModel inner = new MySLOTree.Models.NewsListModel { Seed = node.Id, News = Model.News }; @Html.Partial("_TreeList", inner) } } </ul> }
Результат
Пустой список
Добавление элементов
Отображение списка
Сворачивание\Разворачивание списка
Перемещение элементов
Заключение
Для перемещения элементов в дереве используется drag and drop. Добавление и удаление элементов происходит путем нажатия соответствующих иконок. В статье опущены некоторые моменты. Все подробности можно увидеть в исходном коде.
Полный исходный код доступен на github.
P.S. С радостью отвечу на вопросы и обменяюсь опытом.
ссылка на оригинал статьи http://habrahabr.ru/post/206894/
Добавить комментарий