如何在ASP.NET MVC/Razor中实现弹窗式动态加载TreeView
替换ASP.NET MVC的Datalist为弹窗TreeView(或文本框+浏览按钮)
现有代码回顾
原CSHTML代码(生成带datalist的文本框):
<div class="data-input-group"> @Html.LabelFor(m => m.SourceTag) @Html.EditorFor(m => m.SourceTag, new { htmlAttributes = new { list = "source-tag-list", style = "width: 750px" } }) @Html.ValidationMessageFor(m => m.SourceTag) </div> <datalist id="source-tag-list"></datalist>
最终生成的HTML:
<div class="data-input-group"> <label for="SourceTag">Source Tag Name</label> <input class="text-box single-line valid" data-val="true" data-val-required="The Source Tag Name field is required." id="SourceTag" list="source-tag-list" name="SourceTag" style="width: 750px" type="text" value="" aria-describedby="SourceTag-error" aria-invalid="false"> <span class="field-validation-valid" data-valmsg-for="SourceTag" data-valmsg-replace="true"></span> </div> <datalist id="source-tag-list"> <option value="This is drop down level 1.This is drop down level 2."></option> </datalist>
方案一:文本框+浏览弹窗(简单实现)
1. 修改CSHTML结构
添加浏览按钮,移除原datalist:
<div class="data-input-group"> @Html.LabelFor(m => m.SourceTag) @Html.EditorFor(m => m.SourceTag, new { htmlAttributes = new { style = "width: 750px", @readonly = "readonly" } }) @Html.ValidationMessageFor(m => m.SourceTag) <button type="button" id="browseSourceTag" class="btn btn-primary ml-2">浏览</button> </div>
2. 添加Bootstrap模态框(弹窗容器)
在页面末尾添加弹窗代码:
<div class="modal fade" id="tagTreeModal" tabindex="-1" role="dialog" aria-labelledby="tagTreeModalLabel" aria-hidden="true"> <div class="modal-dialog modal-lg" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="tagTreeModalLabel">选择Source Tag</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <div id="sourceTagTree"></div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button> <button type="button" class="btn btn-primary" id="confirmTagSelect">确认选择</button> </div> </div> </div> </div>
3. 后端添加懒加载接口
在对应控制器中实现返回子节点的接口:
// 假设标签实体类为SourceTag,包含Id、Name、ParentId字段 public JsonResult GetChildTags(int parentId = 0) { var childTags = db.SourceTags .Where(t => t.ParentId == parentId) .Select(t => new { id = t.Id, text = t.Name, children = db.SourceTags.Any(c => c.ParentId == t.Id) }).ToList(); return Json(childTags, JsonRequestBehavior.AllowGet); }
4. 前端脚本实现交互
引入jQuery和jsTree(可通过NuGet或CDN添加),添加以下脚本:
$(function() { // 初始化懒加载树 $('#sourceTagTree').jstree({ 'core': { 'data': function(node, callback) { var parentId = node.id === '#' ? 0 : node.id; $.get('/YourController/GetChildTags', { parentId: parentId }, function(data) { callback.call(this, data); }); }, 'multiple': false } }); // 打开弹窗 $('#browseSourceTag').click(function() { $('#tagTreeModal').modal('show'); }); // 确认选择后回填文本框 $('#confirmTagSelect').click(function() { var selectedNode = $('#sourceTagTree').jstree('get_selected')[0]; if (selectedNode) { $('#SourceTag').val($('#sourceTagTree').jstree('get_text', selectedNode)); $('#tagTreeModal').modal('hide'); } }); });
方案二:无插件手动实现树(极简版)
如果不想用第三方插件,可手动实现简单懒加载树:
1. 修改模态框内的树容器
<div class="modal-body"> <ul id="sourceTagTree" class="tree-view"> <!-- 根节点将通过脚本加载 --> </ul> </div>
2. 前端脚本实现懒加载
$(function() { // 加载根节点 loadChildNodes(0, $('#sourceTagTree')); $('#browseSourceTag').click(function() { $('#tagTreeModal').modal('show'); }); $('#confirmTagSelect').click(function() { var selectedText = $('.tree-view .selected').text(); if (selectedText) { $('#SourceTag').val(selectedText); $('#tagTreeModal').modal('hide'); } }); // 加载子节点函数 function loadChildNodes(parentId, container) { $.get('/YourController/GetChildTags', { parentId: parentId }, function(data) { container.empty(); $.each(data, function(index, tag) { var li = $('<li>' + tag.text + '</li>'); if (tag.children) { var expandBtn = $('<span class="expand-btn">+</span>'); li.prepend(expandBtn); var childUl = $('<ul class="child-nodes"></ul>'); li.append(childUl); expandBtn.click(function() { if (childUl.is(':empty')) loadChildNodes(tag.id, childUl); childUl.toggle(); $(this).text($(this).text() === '+' ? '-' : '+'); }); } li.click(function(e) { e.stopPropagation(); $('.tree-view .selected').removeClass('selected'); $(this).addClass('selected'); }); container.append(li); }); }); } });
3. 添加基础样式
.tree-view { list-style: none; padding-left: 20px; } .tree-view .child-nodes { display: none; list-style: none; padding-left: 20px; } .expand-btn { cursor: pointer; margin-right: 5px; color: #007bff; } .tree-view .selected { background-color: #e9ecef; font-weight: bold; }
注意事项
- 将
YourController替换为实际的控制器名称 - 调整数据库查询逻辑以匹配你的业务实体字段
- 确保项目已引入Bootstrap和jQuery(可通过NuGet安装对应包)
- 若允许用户手动输入文本,可移除文本框的
readonly属性
内容的提问来源于stack exchange,提问作者Graeme
相关产品推荐
相关产品推荐

