Asp.net mvc 如何使用树创建动态菜单

Asp.net mvc 如何使用树创建动态菜单,asp.net-mvc,angular,primeng,Asp.net Mvc,Angular,Primeng,我有一个Angular项目,但这与Angular没有直接关系,我只需要使用树创建动态菜单的逻辑,它也可以类似于ASP.NET MVC项目。所以,你对ASP.NETMVC等的建议也会对我有所帮助 我使用并希望从MSSQL数据库中的表中获取菜单: 菜单表(数据已更改,例如用法): 为了填充菜单项,我需要生成一个JSON字符串,如下所示: { "data": [ { "label": "Documents", "data

我有一个Angular项目,但这与Angular没有直接关系,我只需要使用树创建动态菜单的逻辑,它也可以类似于ASP.NET MVC项目。所以,你对ASP.NETMVC等的建议也会对我有所帮助

我使用并希望从MSSQL数据库中的表中获取菜单:

菜单表(数据已更改,例如用法):

为了填充菜单项,我需要生成一个JSON字符串,如下所示:

{
    "data": 
    [
        {
            "label": "Documents",
            "data": "Documents Folder",
            "expandedIcon": "fa-folder-open",
            "collapsedIcon": "fa-folder",
            "children": [{
                    "label": "Work",
                    "data": "Work Folder",
                    "expandedIcon": "fa-folder-open",
                    "collapsedIcon": "fa-folder",
                    "children": [{"label": "Expenses.doc", "icon": "fa-file-word-o", "data": "Expenses Document"}, {"label": "Resume.doc", "icon": "fa-file-word-o", "data": "Resume Document"}]
                },
                {
                    "label": "Home",
                    "data": "Home Folder",
                    "expandedIcon": "fa-folder-open",
                    "collapsedIcon": "fa-folder",
                    "children": [{"label": "Invoices.txt", "icon": "fa-file-word-o", "data": "Invoices for this month"}]
                }]
        },
        ... //omitted for brevity
    ]
}

所以,我对逻辑和数据库表设计(菜单)一无所知。我应该在控制器或其他地方生成上面的JSON吗?你能就这个问题发表一些建议和范例吗

您的数据库
菜单
表可以使用插件生成treeview,但如果需要,您可能需要为
数据
属性添加一个附加属性。但是,我建议您将
ParentId
属性设置为null,以便您的顶级项(
Documents
)具有
null
值,而不是
0

为了以这种格式传递json,您的模型需要

public class MenuVM
{
    public int Id { get; set; } // this is only used for grouping
    public string label { get; set; }
    public string expandedIcon { get; set; }
    public string collapsedIcon { get; set; }
    public string icon { get; set; }
    public IEnumerable<MenuVM> children { get; set; }
}
以匹配api中的属性

您还需要
数据
属性的父模型

public class TreeVM
{
    public IEnumerable<MenuVM> data { get; set; }
}

对于你的图标,你应该考虑一些<代码> const <代码>值,或者<代码> EnUM <代码>,而不是硬编码字符串。

@斯蒂芬穆克·希斯蒂芬,抱歉,但我对这个问题没有任何经验。如果你有时间,你能举个例子吗?或者给我推荐一个web上的示例使用页面?提前谢谢…@StephenMuecke亲爱的Stephane,我病了,不能看你的答案。你为什么要删除它?你能再寄一次吗((哦,非常感谢!。我会尽快尝试并通知您结果…投票+我只能假设您没有使用System.Linq;
.ToLookup()
.GroupBy()类似。)
-即它通过
ParentId
属性对每条记录进行分组。这两条记录之间的区别在对的回答中进行了解释。此时,我们有一个组
Key=null
包含一条记录(文档),另一个组
Key=1
包含两条记录(工作和家庭)等等这就是我们以后用来为每个菜单分配
子菜单的集合。但是现在我们需要获取每个记录,以便分配
子菜单。我们可以再次调用数据库,但我们使用
。SelectMany()
将项目再次展平为单个集合。最后,我们只需要“顶级”项目,即具有
ParentId=null
的项目(因为它现在包含populate
Children
属性),因此我们使用
groups[null]
,它查找具有
Key=null的组。(请注意,如果您没有将
ParentId`更改为
int?
,并且按照您的原始代码,“顶层”的ParentId=0
,那么它应该是
组[0]
public string data { get; set; }
public class TreeVM
{
    public IEnumerable<MenuVM> data { get; set; }
}
// Sort and group the menu items
var groups = db.Menus
    .OrderBy(x => x.ParentId).ThenBy(x => x.Order)
    .ToLookup(x => x.ParentId, x => new MenuVM
    {
        Id = x.Id,
        label = x.Name
    });
// Assign children
foreach (var item in groups.SelectMany(x => x))
{
    item.children = groups[item.Id].ToList();
    if (item.children.Any())
    {
        .... // apply some logic if there a child items, for example setting 
             // the expandedIcon and collapsedIcon properties
    }
    else
    {
        .... // apply some logic if there are no child items, for example setting 
             // the icon properties - e.g. item.icon = "fa-file-word-o";
    }
}
// Initialize model to be passed to the view
TreeVM model = new TreeVM
{
    data = groups[null].ToList();
}
return Json(model, JsonRequestBehavior.AllowGet);