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

如何在ASP.NET Core中将自引用数据结构展示为Tree View?

解决方案:自引用Person类的树形视图实现

方法1:完善Tag Helper的递归渲染逻辑

你当前的Tag Helper已经处理了根节点,但缺少递归渲染子节点的核心逻辑。另外,不建议在Tag Helper中直接访问_context(违反MVC关注点分离原则),最好通过Tag Helper属性接收传递过来的Person列表,让控制器负责数据查询。

步骤1:重构Tag Helper,添加递归渲染方法

[HtmlTargetElement("people-tree")]
public class PeopleTreeTagHelper : TagHelper
{
    // 通过视图传递的Person列表
    [HtmlAttributeName("people")]
    public List<Person> People { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "div";
        var builder = new StringBuilder();
        builder.Append("<ul class='treeview mb-1 pl-3 pb-2'>");
        
        // 筛选并渲染所有根节点(Parent为null的节点)
        foreach (var rootPerson in People.Where(p => p.Parent == null))
        {
            RenderPersonNode(builder, rootPerson);
        }
        
        builder.Append("</ul>");
        output.Content.SetHtmlContent(builder.ToString());
    }

    // 递归渲染单个Person节点及其子节点
    private void RenderPersonNode(StringBuilder builder, Person person)
    {
        // 渲染当前节点的基础HTML
        builder.AppendFormat("<li><i class='fas fa-angle-right rotate' id='rotate-{0}'></i><span><i class='far fa-envelope-open ic-w mx-1'></i>{1}</span>", person.Id, person.Name);
        
        // 如果有子节点,递归渲染
        if (person.Children != null && person.Children.Count > 0)
        {
            builder.Append("<ul class='treeview-child pl-3'>");
            foreach (var child in person.Children)
            {
                RenderPersonNode(builder, child); // 递归调用,处理子节点
            }
            builder.Append("</ul>");
        }
        
        builder.Append("</li>");
    }
}

步骤2:在视图中使用Tag Helper

首先在_ViewImports.cshtml中注册你的Tag Helper(假设它在YourProject.TagHelpers命名空间下):

@addTagHelper *, YourProject

然后在HierarchicalDataStructure.cshtml视图中传递数据:

@model PersonListModel

<people-tree people="@Model.People"></people-tree>

步骤3:保留原Controller Action(无需修改)

你的原Action已经正确获取了包含子节点的Person列表,直接复用即可:

public IActionResult HierarchicalDataStructure() {
    var people = new PersonListModel(_context) { People = _context.People.Include(i => i.Children).ToList() };
    return View(people);
}

方法2:使用前端组件渲染JSON数据

如果你已经能通过Action获取正确的树形JSON,可以写一个视图,用JavaScript递归渲染或者使用现成的树形组件(比如Bootstrap Treeview、jQuery Treeview等)。

步骤1:创建视图HierarchicalDataStructure.cshtml

@{
    ViewData["Title"] = "People Hierarchy";
}

<h1>Person Hierarchical Tree</h1>
<div id="people-tree-container"></div>

@section Scripts {
    <script>
        // 从后端获取树形JSON数据
        fetch('@Url.Action("GetPeopleTreeJson")')
            .then(response => response.json())
            .then(data => {
                renderTree(data.data, document.getElementById('people-tree-container'));
                addToggleEvents(); // 添加折叠/展开事件
            });

        // 递归渲染树形结构
        function renderTree(nodes, container) {
            const ul = document.createElement('ul');
            ul.className = 'treeview mb-1 pl-3 pb-2';
            
            nodes.forEach(node => {
                const li = document.createElement('li');
                li.innerHTML = `
                    <i class='fas fa-angle-right rotate'></i>
                    <span><i class='far fa-envelope-open ic-w mx-1'></i>${node.Name}</span>
                `;
                
                if (node.Children && node.Children.length > 0) {
                    const childUl = document.createElement('ul');
                    childUl.className = 'treeview-child pl-3';
                    renderTree(node.Children, childUl);
                    li.appendChild(childUl);
                }
                
                ul.appendChild(li);
            });
            
            container.appendChild(ul);
        }

        // 添加折叠/展开交互
        function addToggleEvents() {
            document.querySelectorAll('.rotate').forEach(icon => {
                icon.addEventListener('click', function() {
                    const parentLi = this.closest('li');
                    parentLi.classList.toggle('open');
                });
            });
        }
    </script>
}

步骤2:新增返回JSON的Controller Action

public IActionResult GetPeopleTreeJson()
{
    var rootPeople = _context.People
        .Include(i => i.Children)
        .Where(x => x.Parent == null)
        .ToList();
        
    return Json(new { data = rootPeople });
}

步骤3:添加基础样式(可选)

为了让树形结构更美观,添加以下CSS实现折叠/展开的视觉效果:

.treeview-child {
    display: none; /* 默认隐藏子节点 */
}
.treeview li.open > .treeview-child {
    display: block;
}
.rotate {
    cursor: pointer;
    transition: transform 0.2s;
}
.treeview li.open > .rotate {
    transform: rotate(90deg);
}

内容的提问来源于stack exchange,提问作者Burak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:38:39