我有一个如下的分层数据表,它生成菜单及其子菜单。主菜单的parentId为0.子菜单有父ID引用parentId。
ResourceId DisplayName ParentId Url
-----------------------------------------------
1 Home 0 Some Url
2 Student 0 Some Url
3 Staff 0 Some Url
4 Library 0 Some Url
6 StudentAtt 1 Some Url
7 TimeTable 1 Some Url
8 Staff Att 2 Some Url
9 Book Issue 3 Some Url
10 Book Return 3 Some Url
11 Fee Payment 4 Some Url
12 Book fine 10 Some Url

需要将其转换为Json。下面是我试过的代码。我试图检查SubMenu的ParentId是否等于主菜单的ResourceId。但是不显示subMenu。 (变量表是DataTable)
var rows = table.Rows.Cast<DataRow>().ToList();
var result = rows.Where(x => x["ParentId"].ToString() == "0").GroupBy(r => new { x = r["ResourceId"] }).Select(
g => new
{
//MenuLevel = g.Key.x,
MenuDetails = g.GroupBy(r => new {a = r["DisplayName"], b = r["Url"]}).Select(
detail => new
{
DisplayName = detail.Key.a,
Url = detail.Key.b,
SubMenu =
detail.Where(y => g.Key.x.ToString()==y["ParentId"].ToString()).
GroupBy(r => new {f = r["DisplayName"]}).Select(
subMenu=>new
{
SubMenuDisplayName=subMenu.Key.f
}
)
}
)
});
&#13;
我得到的结果如下。
[{"MenuDetails":[{"DisplayName":"Home","Url":null,"SubMenu":[]}]},{"MenuDetails":[{"DisplayName":"Student","Url":null,"SubMenu":[]}]},{"MenuDetails":[{"DisplayName":"Staff","Url":null,"SubMenu":[]}]},{"MenuDetails":[{"DisplayName":"Library","Url":null,"SubMenu":[]}]}]
但预期结果是:
[{"MenuDetails":[{"DisplayName":"Home","Url":null,"SubMenu":[{"SubMenuDisplayName":"StudentAtt"},{"SubMenuDisplayName":"TimeTable"}]}]},{"MenuDetails":[{"DisplayName":"Student","Url":null,"SubMenu":[{"SubMenuDisplayName":"Staff Att"}]}]},{"MenuDetails":[{"DisplayName":"Staff","Url":null,"SubMenu":[{"SubMenuDisplayName":"Book Issue"},{"SubMenuDisplayName":"Book Return"}]}]},{"MenuDetails":[{"DisplayName":"Library","Url":null,"SubMenu":[{"SubMenuDisplayName":"Fee Payment "}]}]}]
我还需要显示子子菜单(其父ID指向子菜单的资源ID)任何一个请帮助
答案 0 :(得分:0)
您的问题在
SubMenu = detail.Where(y => ...
,详细信息已经过滤到rows.Where(x => x["ParentId"].ToString() == "0")
,因此它不包含子项。
这将更接近你想要的但只返回前两个级别。
var result = rows.Where(x => x["ParentId"].ToString() == "0").GroupBy(r => new { x = r["ResourceId"] }).Select(
g => new {
//MenuLevel = g.Key.x,
MenuDetails = g.GroupBy(r => new { a = r["DisplayName"], b = r["Url"] }).Select(
detail => new {
DisplayName = detail.Key.a,
Url = detail.Key.b,
SubMenu =
rows.Where(y => g.Key.x.ToString() == y["ParentId"].ToString()).
GroupBy(r => new { f = r["DisplayName"] }).Select(
subMenu => new {
SubMenuDisplayName = subMenu.Key.f
}
)
}
)
});
要创建完整的层次结构,您需要为每个菜单项创建对象,然后将它们连接在一起。如果您创建一个表示菜单项的类型,则会更容易,例如:
public class MenuDeatils {
public int ID;
public string Url;
public string DisplayName;
public IEnumerable<MenuDeatils> SubMenu;
}
然后,您可以为每个项目创建一个对象,并按其ParentIds对其进行分组:
var groups = (from row in rows
group row by row["ParentId"] into parentGroup
select new {
Key = (int)parentGroup.Key,
Items = parentGroup.Select(r => new MenuDeatils {
ID = (int)r["ResourceId"],
DisplayName = (string)r["DisplayName"],
Url = (string)r["Url"]
})
}).ToList();
注意:这里列举了查询(.ToList()),因此我们创建了一组MenuDeatils对象。
接下来,我们可以从我们创建的组中设置每个MenuDetails对象的SubMenu属性。
foreach (var menuItem in groups.SelectMany(g => g.Items)) {
var submenu = groups.SingleOrDefault(g => g.Key == menuItem.ID);
if (submenu != null) {
menuItem.SubMenu = submenu.Items;
}
};
可以在以下位置找到顶级项目:
var result = groups.Single(g => g.Key == 0).Items
,现在已附上所有后代菜单。