ASP.NET Core MVC如何基于MSSQL数据实现多级课程模块TreeView
问题描述
我想在ASP.NET Core MVC项目中实现一个多级TreeView列表,列表内容包含课程与模块,每门课程下关联多个模块,每个模块还可嵌套多级子模块,所有数据存储在MSSQL数据库中,期望实现的层级结构如下:
- 1 A
- 1.1 AA
- 1.1.1 AAA
- 1.1 AA
以下是我已编写的相关代码:
模型代码
using System; using System.Collections.Generic; namespace Courses.Models { public class ErrorViewModel { public string RequestId { get; set; } public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); } public class Courses { public int Id { get; set; } public string Title { get; set; } } public class Modules { public int Id { get; set; } public int CourseId { get; set; } public int ParentId { get; set; } public int Order { get; set; } public string Title { get; set; } public string Num { get; set; } } public class TreeViewNode { public string id { get; set; } public string parent { get; set; } public string text { get; set; } } }
控制器代码
using Courses.Models; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using System.Collections.Generic; namespace Courses.Controllers { public class HomeController : Controller { private DBCtx Context { get; } public HomeController(DBCtx _context) { this.Context = _context; } public IActionResult Index() { List<TreeViewNode> nodes = new List<TreeViewNode>(); //循环添加父节点 foreach (Models.Courses type in this.Context.Courses) { nodes.Add(new TreeViewNode { id = type.Id.ToString(), parent = "#", text = type.Title }); } //循环添加子节点 foreach (Modules subType in this.Context.Modules)//此处利用了数据库的设计特性 { if (subType.ParentId == 0) { nodes.Add(new TreeViewNode { id = subType.Id.ToString(), parent = subType.CourseId.ToString(), text = subType.Num + " " + subType.Title }); } else nodes.Add(new TreeViewNode { id = subType.Id.ToString(), parent = subType.ParentId.ToString(), text = subType.Num + " " + subType.Title }); } //序列化为JSON字符串 ViewBag.Json = JsonConvert.SerializeObject(nodes); return View(); } } }
视图代码
@addTagHelper*, Microsoft.AspNetCore.Mvc.TagHelpers @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> </head> <body> <div id="jstree"> </div> <form method="post" asp-controller="Home" asp-action="Index"> <input type="hidden" name="selectedItems" id="selectedItems" /> </form> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" /> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.1/jquery.min.js"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script> <script type="text/javascript"> $(function () { $('#jstree').jstree({ "core": { "themes": { "variant": "large" }, "data": @Html.Raw(ViewBag.Json) }, "plugins": ["sort","wholerow"], }); }); </script> </body> </html>
问题
当前运行后层级结构显示异常,需要调整哪些部分才能实现预期的多级TreeView效果?
解决方案
你当前代码的核心问题是课程ID和模块ID存在重复可能,jstree无法识别重复ID的节点层级,其次是排序逻辑不符合需求,按以下步骤调整即可:
- 扩展TreeViewNode模型,新增排序字段,后续用来实现自定义排序:
public class TreeViewNode { public string id { get; set; } public string parent { get; set; } public string text { get; set; } public int order { get; set; } }
- 修改控制器节点生成逻辑,给课程和模块的ID加不同前缀,避免ID重复:
public IActionResult Index() { List<TreeViewNode> nodes = new List<TreeViewNode>(); // 添加课程根节点 foreach (Models.Courses course in this.Context.Courses) { nodes.Add(new TreeViewNode { id = $"course_{course.Id}", parent = "#", text = course.Title, order = 0 }); } // 添加模块节点 foreach (Modules module in this.Context.Modules) { string parentId = module.ParentId == 0 ? $"course_{module.CourseId}" : $"module_{module.ParentId}"; nodes.Add(new TreeViewNode { id = $"module_{module.Id}", parent = parentId, text = $"{module.Num} {module.Title}", order = module.Order }); } ViewBag.Json = JsonConvert.SerializeObject(nodes); return View(); }
- 修改视图jstree配置,自定义排序规则按你数据库的Order字段排序,替代默认的文本排序:
$(function () { $('#jstree').jstree({ "core": { "themes": { "variant": "large" }, "data": @Html.Raw(ViewBag.Json) }, // 自定义排序逻辑 "sort": function(a, b) { return this.get_node(a).original.order > this.get_node(b).original.order ? 1 : -1; }, "plugins": ["sort","wholerow"], }); });
如果需要更规范的数据库设计,可以把Modules表的ParentId字段改成可空类型,用NULL代表一级模块,逻辑对应调整即可。
内容的提问来源于stack exchange,提问作者Kamil
相关产品推荐
相关产品推荐

