要模仿您所指的解决方案,您必须向您的实体添加至少一个导航属性。这样您就可以有效地枚举每个ProductCategory 的孩子。
我建议使用以下实体声明,这不会对数据库造成额外的副作用。为方便起见,它有两个 Navigation 属性:
public class ProductCategory
{
public int Id { get; set; }
public string Title { get; set; }
[ForeignKey(nameof(ParentCategory))]
public int? ParentId { get; set; }
public ProductCategory ParentCategory { get; set; } //nav.prop to parent
public ICollection<ProductCategory> Children { get; set; } //nav. prop to children
}
现在,如果您有一个很好地填充了 ParentCategory 记录的数据库集,您可以在操作方法中查询它,如下所示:
public IActionResult Index()
{
//get all categories, so we have each and every child in Context
var categories = yourDbContext.ProductCategories.Include(e => e.Children).ToList();
//only need top level categories in the View
var topLevelCategories = categories.Where(e => e.ParentId == null);
return View(topLevelCategories);
}
然后,此视图会将这些顶级类别作为模型(我强烈建议为此创建一个 ViewModel),并使用 Partial 递归地渲染所有子项:
@model IEnumerable<ProductCategory>
<table>
@Html.Partial("CategoryRowPartial", Model)
</table>
最后,CategoryRowPartial,也接收一个IEnumerable<ProductCategory> 看起来像这样。它以递归方式调用自身以显示所有子项:
@model IEnumerable<ProductCategory>
@foreach (var category in Model)
{
<tr><td>@category.Title</td></tr>
@Html.Partial("CategoryRowPartial", category.Children)
}
现在,这并没有考虑每个孩子的水平,也没有考虑到空的(而且相当草率的)td's & colspans。就个人而言,我会为此使用<ul> 或<ol>。它们旨在用于显示层次结构。
如果你坚持使用<table>,我再次建议创建一个专门的视图模型,它可以保存每个表格行的“深度”。