Wiki
Clone wikiBoot.Multitenancy / Hierarchy feature
#Hierarchy feature#
This lets you create a hierarky of any object that inherits the Node class. Lets say you want to create a simple UL LI list. This is very easy with this class. This feature also allow us to create JSon data in a second. Let me show you an example.
Create a model SiteNode:
#!c# using Boot.Multitenancy.Intrastructure.Domain; <!--Important--> namespace...... public class SiteNode : Node, IEntity //<!----Inherit Node class { public virtual string Text { get; set; } public virtual string Url { get; set; } } public class SiteNodeMap : Entity<SiteNode> { public SiteNodeMap() { //Id and ParentId is inherited from base class so dont add these in SiteNode class. Id(x => x.Id) .Column("Id") .GeneratedBy.Assigned() .CustomType<Int32>(); Map(p => p.ParentId); Map(p => p.Text); Map(p => p.Url); } } //For simplicity I added this code in HomeController, but its better to have a viewmodel, repo... public ActionResult Index() { var treeData = Host.Open().All<SiteNode>() .ToBaseList() //Extension that Adds a Parent Child relation .TreeView(c => c.Nodes, c => c.Data.Text, c=> c.Data.Url); return View("Index", "_Layout", treeData); } 1. In model just add @Html.Raw(Model) 2. Start the site to create the table. 3. Open the table and add some items in it. For eg: 1, 0, Root, /home 2, 1, Sub 1.1, /sub1.1 .....
#Flatten# If you need to flatten your data add this method below as an extension. I will add it in the next release. Flatten a hierarchy makes it possible to print out items in the order their created in the hierarchy. Useful when for example creating a Treegrid or as I did for my Widget, Page Mini Admin.
#!c# private static IEnumerable<NodeBase<T>> Flatten<T>(this IEnumerable<NodeBase<T>> items, Func<NodeBase<T>, IEnumerable<NodeBase<T>>> getChildren) { var stack = new Stack<NodeBase<T>>(); foreach (var item in items) stack.Push(item); while (stack.Count > 0) { var current = stack.Pop(); yield return current; var children = getChildren(current); if (children == null) continue; foreach (var child in children) stack.Push(child); } } public static IEnumerable<NodeBase<T>> ToFlatten<T>(this IEnumerable<NodeBase<T>> items) { return items.Flatten(c=> c.Nodes).Reverse(); } //Example use: Pages.ToBaseList().ToFlatten().ToList().ForEach(c => { var hasNodes = Pages.Where(x=> x.Id == c.Data.ParentId); var parent = hasNodes.Any() ? " - " : ""; model.PageList +=string.Format(template, c.Data.Id, c.Data.Text, c.Data.Url, parent, c.Data.Icon, c.Data.ParentId); });
JSon
It easy to render data as a JsonResult.
#!c# public ActionResult Output() { var treeData = Host.Open() .All<SiteNode>() .ToBaseList() .ToHierarchy(); return Json(treeData, JsonRequestBehavior.AllowGet); } Output: [ { "Data": { "Text": "TestRoot", "Url": "/", "Id": 1, "ParentId": 0 }, "Nodes": [ { "Data": { "Text": "TestSub", "Url": "/test", "Id": 2, "ParentId": 1 }, "Nodes": [], "Parent": null } ], "Parent": null }, { "Data": { "Text": "Forum", "Url": "/forum", "Id": 3, "ParentId": 0 }, "Nodes": [ { "Data": { "Text": "Threads", "Url": "/treads", "Id": 4, "ParentId": 3 }, "Nodes": [], "Parent": null } ], "Parent": null } ]
#What's next# Currenctly I'm not satisfied with the ordering of items. I'm working on the next release where I added a Position comparer. Will also change the INode infrastructure to make it more easy to use since it's in a generic package.
The new structure as follows:
- Node 1
- Node 1.1
- Node 2
- Node 2.1
- Node 2.2 ....
#!c# public interface INode<T> { Int32 Id { get; set; } Int32 ParentId { get; set; } List<T> Nodes { get; set; } string Position {get; set; } } //Makes it much more simpler. public class SiteNode : INode<SiteNode>, IEntity{} .... public static IEnumerable<T> OrderByPosition<T>(this IEnumerable<INode<T>> collection) { return collection .OrderBy(menuPartEntry => menuPartEntry .Position, new PositionComparer()) .Cast<T>() .ToList(); } public static void ReOrder<T>(this IEnumerable<INode<T>> collection, Action<INode<T>> save) .......
Updated