asp.net-mvc ASP.NET MVC 4 使用递归局部视图生成树视图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17553286/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ASP.NET MVC 4 generating a treeview with recursive partial view
提问by user2082422
I have a partial view in an MVC 4 project, which is strongly typed. It takes an IEnumerable collection of a table of a database. In that table there are IDs, Names, and ParentIDs for storing hierarchical connection between records. The view that calls the partial view is also strongly typed, it takes the whole database as the model, and passes the Categories table to the partial view, as an enumerable collection:
我在 MVC 4 项目中有一个部分视图,它是强类型的。它需要一个数据库表的 IEnumerable 集合。在该表中有用于存储记录之间的分层连接的 ID、名称和父 ID。调用分部视图的视图也是强类型的,它以整个数据库为模型,将 Categories 表作为可枚举集合传递给分部视图:
@Html.Partial("_TreeCategories", @Model.Categories.ToList())
And in the partial view, I want to take the root nodes first, so I can extend the whole tree in a recursive way. In the database table, all records are considered as root nodes with a ParentID == null.
So generally, my way to do this would look like:
而在局部视图中,我想先取根节点,这样我就可以递归地扩展整个树。在数据库表中,所有记录都被视为具有 ParentID == null 的根节点。
所以一般来说,我这样做的方式是这样的:
@model IEnumerable<TreeCollections.OpenAccess.Category>
@if (Model.ToList().Count >= 0)
{
@if (Model.ToList()[0].Parent_id == null)
{
<text><ul id="navigation"></text>
}
@foreach (var node in @Model)
{
<li><a href="[email protected]">@node.Name</a>
@foreach (var subNode in @Model.Where(s => s.Parent_id == node.Id))
{
@Html.Partial("_TreeCategories", subNode)
}
</li>
}
@if (Model.ToList()[0].Parent_id == null)
{
</ul>
}
}
So I check if the first element's ParentID of the Model is null, and if it is, then it should create a < ul> tag with the id "navigation", so the jquery plugin can recognise that it is meant to be a treeview control. Then it creates a list tag with a recursive call within. The recursively called partial view takes the children of the node as the model. And lastly if we arrived to the end of the partial view's rendering, and we are at the "root level", it should write a closing < ul> tag
There are some problems, however. First, at the end, that closing unordered list tag is wrong, VS can't find the matching start tag for that. Second, I don't know why, but at the top, I can put the starter < ul> tag in between tags, and I can't do it at the closing tag below. But I'm not sure about these < ul > tags either, I feel those are wrong too.
Please, help me, I'm stuck with this for days now.
所以我检查Model的第一个元素的ParentID是否为null,如果是,那么它应该创建一个id为“navigation”的<ul>标签,这样jquery插件就可以识别它是一个树视图控件. 然后它创建一个带有递归调用的列表标签。递归调用的局部视图以节点的子节点为模型。最后,如果我们到达局部视图渲染的结尾,并且我们处于“根级别”,它应该写一个结束 <ul> 标记
但是,也存在一些问题。首先,最后,关闭无序列表标签是错误的,VS 找不到与之匹配的开始标签。其次,我不知道为什么,但是在顶部,我可以将 starter <ul> 标签放在标签之间,而我不能在下面的结束标签处这样做。但我也不确定这些 < ul > 标签,我觉得这些也是错误的。
请帮助我,我已经被这个问题困扰了好几天了。
回答by hubson bropa
man, you got some wonk going on here. i feel your pain on getting stuck.
伙计,你在这里遇到了一些怪人。我感觉到你被卡住的痛苦。
see if this floats your boat.
看看这能不能让你的船漂浮起来。
you need a seed value to keep track of what you are looking for in the listing when you do recursion on the same list. it's better to do a parent children mapping in the class, but meh this was fun to do given your structure and should do the trick.
当您在同一列表上进行递归时,您需要一个种子值来跟踪您在列表中查找的内容。最好在课堂上进行父子映射,但是鉴于您的结构,这样做很有趣,并且应该可以解决问题。
Models
楷模
namespace trash.Models
{
public class Category
{
public int ID { get; set; }
public int? Parent_ID { get; set; }
public string Name {get; set;}
}
public class SeededCategories
{
public int? Seed { get; set; }
public IList<Category> Categories { get; set; }
}
}
Controller (NOTE: you start the recursion chain by setting the Seed property to null which will pick up all the null parents)
控制器(注意:您通过将 Seed 属性设置为 null 来启动递归链,这将获取所有空父项)
namespace trash.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
IList<trash.Models.Category> categories = new List<trash.Models.Category>();
categories.Add(new trash.Models.Category { ID = 1, Parent_ID = null, Name = "Top1" });
categories.Add(new trash.Models.Category { ID = 2, Parent_ID = null, Name = "Top2" });
categories.Add(new trash.Models.Category { ID = 3, Parent_ID = 1, Name = "Top1Ring1" });
categories.Add(new trash.Models.Category { ID = 4, Parent_ID = 1, Name = "Top1Ring2" });
trash.Models.SeededCategories model = new Models.SeededCategories { Seed = null, Categories = categories };
return View(model);
}
}
}
Views Index
浏览量索引
@model trash.Models.SeededCategories
Here's a list
@Html.Partial("_TreeCategories", Model)
Partial (your _TreeCategories. NOTE: set the Seed to the current node ID and volia recursion)
部分(您的 _TreeCategories。注意:将种子设置为当前节点 ID 和 volia 递归)
@model trash.Models.SeededCategories
@if (Model.Categories.Where(s => s.Parent_ID == Model.Seed).Any())
{
<ul>
@foreach (var node in Model.Categories)
{
if (node.Parent_ID == Model.Seed)
{
trash.Models.SeededCategories inner = new trash.Models.SeededCategories { Seed = node.ID, Categories = Model.Categories };
<li><a href="[email protected]">@node.Name</a>
@Html.Partial("_TreeCategories", inner)
</li>
}
}
</ul>
}
回答by Vladimir Georgiev
You can try Shield UI's recursive TreeView for ASP.NET MVC.
您可以尝试 Shield UI 的递归TreeView for ASP.NET MVC。
It allows you to specify all the TreeView items using a RecursiveDataSource object, which can be setup to retrieve the data for a tree item from a remote endpoint or a local source "lazily", whenever the item is being expanded.
它允许您使用 RecursiveDataSource 对象指定所有 TreeView 项目,该对象可以设置为在项目展开时从远程端点或本地源“延迟”检索树项目的数据。
The RecursiveDataSource is a wrapper around a JavaScript DS widget, which introduces the need for some JS code, as well as updating your server code that will provide the data (either implementing a web service, or place the data in a JS variable in your view).
RecursiveDataSource 是 JavaScript DS 小部件的包装器,它引入了对一些 JS 代码的需求,以及更新将提供数据的服务器代码(要么实现 Web 服务,要么将数据放在视图中的 JS 变量中)。

