diff --git a/TreeViewInMVC/App_Data/database-20230407.sql b/TreeViewInMVC/App_Data/database-20230407.sql new file mode 100644 index 0000000..4fdef4f Binary files /dev/null and b/TreeViewInMVC/App_Data/database-20230407.sql differ diff --git a/TreeViewInMVC/Binders/TreeModelBinder.cs b/TreeViewInMVC/Binders/TreeModelBinder.cs new file mode 100644 index 0000000..0b180f7 --- /dev/null +++ b/TreeViewInMVC/Binders/TreeModelBinder.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Mvc; +using TreeViewInMVC.Models; +using Newtonsoft.Json; + +namespace TreeViewInMVC.Binders +{ + public class TreeModelBinder : IModelBinder + { + public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) + { + HttpRequestBase request = controllerContext.HttpContext.Request; + + var listTreeHidden = JsonConvert.DeserializeObject>(request.Form.Get("treeHidden")); + + if (listTreeHidden.Count > 0) + { + var selectedIds = JsonConvert.DeserializeObject>(request.Form.Get("treeHiddenSelected")); + + if (selectedIds.Count > 0) + { + for (int i = 0; i < listTreeHidden.Count; i++) + { + if (selectedIds.Contains(listTreeHidden[i].Id)) + listTreeHidden[i].Selected = true; + } + + } + + if (listTreeHidden.Count > 1) + { + var listWithoutParentId = listTreeHidden.Where(x => x.ParentId == null).ToList(); + + var newlist = new List(); + + for (int i = 0; i < listWithoutParentId.Count; i++) + { + newlist.Add(OrganizeChildrenItems(listWithoutParentId[i], ref listTreeHidden)); + } + + listTreeHidden = newlist; + + } + } + + return listTreeHidden; + } + + TreeModel OrganizeChildrenItems(TreeModel item, ref List list) + { + if (!list.Any(x => x.ParentId == item.Id)) + return item; + + if (item.Childs == null) + item.Childs = new List(); + + foreach (TreeModel child in list.Where(x => x.ParentId == item.Id)) + { + item.Childs.Add(OrganizeChildrenItems(child, ref list)); + } + + return item; + } + } +} \ No newline at end of file diff --git a/TreeViewInMVC/Controllers/HomeController.cs b/TreeViewInMVC/Controllers/HomeController.cs index 2fa298f..7d4f844 100644 --- a/TreeViewInMVC/Controllers/HomeController.cs +++ b/TreeViewInMVC/Controllers/HomeController.cs @@ -1,7 +1,5 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; -using System.Web; using System.Web.Mvc; using TreeViewInMVC.Models; @@ -34,5 +32,11 @@ public ActionResult TreeView() return View(db.TreeModel.Where(x => !x.ParentId.HasValue).ToList()); } + [HttpPost] + public ActionResult TreeView(List model) + { + return View(model); + } + } } \ No newline at end of file diff --git a/TreeViewInMVC/Global.asax.cs b/TreeViewInMVC/Global.asax.cs index 737a0bd..74bf7f7 100644 --- a/TreeViewInMVC/Global.asax.cs +++ b/TreeViewInMVC/Global.asax.cs @@ -5,6 +5,8 @@ using System.Web.Mvc; using System.Web.Optimization; using System.Web.Routing; +using TreeViewInMVC.Binders; +using TreeViewInMVC.Models; namespace TreeViewInMVC { @@ -16,6 +18,8 @@ protected void Application_Start() FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); + + ModelBinders.Binders.Add(typeof(List), new TreeModelBinder()); } } } diff --git a/TreeViewInMVC/Models/IdentityModels.cs b/TreeViewInMVC/Models/IdentityModels.cs index 538c22d..5901b4a 100644 --- a/TreeViewInMVC/Models/IdentityModels.cs +++ b/TreeViewInMVC/Models/IdentityModels.cs @@ -25,6 +25,12 @@ public ApplicationDbContext() { } + protected override void OnModelCreating(DbModelBuilder modelBuilder) + { + Database.SetInitializer(null); + base.OnModelCreating(modelBuilder); + } + public static ApplicationDbContext Create() { return new ApplicationDbContext(); diff --git a/TreeViewInMVC/Models/Tree.cs b/TreeViewInMVC/Models/Tree.cs index bebb65c..6aa78f3 100644 --- a/TreeViewInMVC/Models/Tree.cs +++ b/TreeViewInMVC/Models/Tree.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Reflection.Emit; using System.Web; using System.Web.Mvc; using System.Web.UI; @@ -152,6 +153,9 @@ public override string ToString() var listItems = _items.ToList(); + var div = new TagBuilder("div"); + div.MergeAttribute("id", "jstree"); + var ul = new TagBuilder("ul"); ul.MergeAttributes(_htmlAttributes); var li = new TagBuilder("li") @@ -173,12 +177,41 @@ public override string ToString() } ul.InnerHtml += li.ToString(); - return ul.ToString(); + div.InnerHtml += ul.ToString(); + + var outerDiv = new TagBuilder("div"); + outerDiv.InnerHtml += div.ToString(); + + var hiddenTreeData = new TagBuilder("input"); + hiddenTreeData.MergeAttribute("id", "treeHidden"); + hiddenTreeData.MergeAttribute("name", "treeHidden"); + hiddenTreeData.MergeAttribute("type", "hidden"); + hiddenTreeData.MergeAttribute("value", ""); + + outerDiv.InnerHtml += hiddenTreeData.ToString(); + + var hiddenTreeIdsSelecteds = new TagBuilder("input"); + hiddenTreeIdsSelecteds.MergeAttribute("id", "treeHiddenSelected"); + hiddenTreeIdsSelecteds.MergeAttribute("name", "treeHiddenSelected"); + hiddenTreeIdsSelecteds.MergeAttribute("type", "hidden"); + hiddenTreeIdsSelecteds.MergeAttribute("value", ""); + + outerDiv.InnerHtml += hiddenTreeIdsSelecteds.ToString(); + + return outerDiv.ToString(); } private void AppendChildren(TagBuilder parentTag, T parentItem, Func> childrenProperty) { - var children = childrenProperty(parentItem).ToList(); + + var enumerableList = childrenProperty(parentItem); + + if (enumerableList == null) + { + return; + } + + var children = enumerableList.ToList(); if (!children.Any()) { return; @@ -215,12 +248,25 @@ private TagBuilder GetLi(T item) { if (prop.Name.ToLower() == "id") li.MergeAttribute("id", prop.GetValue(item, null).ToString()); + + if (prop.Name.ToLower() == "title") + li.MergeAttribute("data-title", prop.GetValue(item, null).ToString()); + + if (prop.Name.ToLower() == "description") + li.MergeAttribute("data-description", prop.GetValue(item, null) == null ? "" : prop.GetValue(item, null).ToString()); + + if (prop.Name.ToLower() == "parentid") + li.MergeAttribute("data-parentId", prop.GetValue(item, null) == null ? "" : prop.GetValue(item, null).ToString()); + //li.GenerateId(prop.GetValue(item, null).ToString()); //object propValue = prop.GetValue(myObject, null); // Do something with propValue if (prop.Name.ToLower() == "sortorder") li.MergeAttribute("priority", prop.GetValue(item, null).ToString()); } + + li.MergeAttribute("treeJsElement", "treeJsElement"); + return li; } } diff --git a/TreeViewInMVC/Models/TreeModel.cs b/TreeViewInMVC/Models/TreeModel.cs index 3119823..6c69c9d 100644 --- a/TreeViewInMVC/Models/TreeModel.cs +++ b/TreeViewInMVC/Models/TreeModel.cs @@ -9,6 +9,7 @@ public class TreeModel public string Title { get; set; } public string Description { get; set; } public int? ParentId { get; set; } + public bool Selected { get; set; } [ForeignKey("ParentId")] public virtual TreeModel Parent { get; set; } public virtual ICollection Childs { get; set; } diff --git a/TreeViewInMVC/TreeViewInMVC.csproj b/TreeViewInMVC/TreeViewInMVC.csproj index e246f2f..0222b93 100644 --- a/TreeViewInMVC/TreeViewInMVC.csproj +++ b/TreeViewInMVC/TreeViewInMVC.csproj @@ -25,6 +25,7 @@ + true @@ -167,6 +168,7 @@ + diff --git a/TreeViewInMVC/Views/Home/TreeView.cshtml b/TreeViewInMVC/Views/Home/TreeView.cshtml index 134c65b..e4c259a 100644 --- a/TreeViewInMVC/Views/Home/TreeView.cshtml +++ b/TreeViewInMVC/Views/Home/TreeView.cshtml @@ -4,19 +4,22 @@

TreeView

-
+
+ @*
*@ @(Html.TreeView(Model) - .EmptyContent("root") - .Children(m => m.Childs) - .HtmlAttributes(new { id = "tree" }) - .ChildrenHtmlAttributes(new { @class = "subItem" }) - .ItemText(m => m.Title) - .ItemTemplate( - @ - @item.Title - ) + .EmptyContent("root") + .Children(m => m.Childs) + .HtmlAttributes(new { id = "tree" }) + .ChildrenHtmlAttributes(new { @class = "subItem" }) + .ItemText(m => m.Description) + .ItemTemplate( + @ + @item.Title + ) ) -
+ @*
*@ + +
@section scripts { @@ -43,8 +46,39 @@ "icon": "fa fa-file icon-state-warning icon-lg" } }, - "plugins": ["dnd", "state", "types", "sort", "checkbox"] + "plugins": ["dnd", "state", "types", "sort", "checkbox"], + }); + + $('#jstree').on('changed.jstree', function (e, data) { + var i, j, r = [], m = []; + for (i = 0, j = data.selected.length; i < j; i++) { + r.push(data.instance.get_node(data.selected[i]).id); + } + + $('#treeHiddenSelected').val(JSON.stringify(r)); + }); + }); - + + let list = $("li[treejselement='treeJsElement']").map(function () { return $(this).attr("id"); }).get(); + + var elem = {}, n = []; + + if (list.length > 0) { + + for (var i = 0; i < list.length; i++) { + elem = $("li#" + list[i] + "[treejselement='treeJsElement']"); + n.push({ + Id: list[i], + Title: elem.data("title"), + Description: elem.data("description"), + ParentId: elem.data("parentid") + }); + } + + $('#treeHidden').val(JSON.stringify(n)); + } + + }