You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core MVC如何基于MSSQL数据实现多级课程模块TreeView

问题描述

我想在ASP.NET Core MVC项目中实现一个多级TreeView列表,列表内容包含课程与模块,每门课程下关联多个模块,每个模块还可嵌套多级子模块,所有数据存储在MSSQL数据库中,期望实现的层级结构如下:

  • 1 A
    • 1.1 AA
      • 1.1.1 AAA

以下是我已编写的相关代码:

模型代码

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的节点层级,其次是排序逻辑不符合需求,按以下步骤调整即可:

  1. 扩展TreeViewNode模型,新增排序字段,后续用来实现自定义排序:
public class TreeViewNode
{
    public string id { get; set; }
    public string parent { get; set; }
    public string text { get; set; }
    public int order { get; set; }
}
  1. 修改控制器节点生成逻辑,给课程和模块的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();
}
  1. 修改视图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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 03:15:07