Recursion in a table using razor in ASP.NET Core

你说的曾经没有我的故事 提交于 2019-12-13 02:57:30

问题


I have this product category model:

public class ProductCategory
{
    public int Id { get; set; }
    public int? ParentId { get; set; }
    public string Title { get; set; }
}

Using the parent Id, I want to display a list of categories and sub-categories (max three levels) in a tabeled list, like so:

<table>
    <tr><td colspan="3">Category #1</td></tr>
    <tr><td></td><td>Category #1.1</td><td></td></tr>
    <tr><td></td><td>Category #1.2</td><td></td></tr>
    <tr><td colspan="2"></td><td>Category #1.2.1</td></tr>
    <tr><td colspan="2"></td><td>Category #1.2.2</td></tr>
    <tr><td colspan="3">Category #2</td></tr>
</table>

I tried to implement this solution, but I don't understand how I'm supposed to pass the data to the partial view. And my categories don't have a reference to children, but rather to parents.


回答1:


To mimic the solution you refer to, you'd have to add at least one Navigation Property to your entity. This way you can effectively enumerate the children of each ProductCategory.

I would suggest the following entity declaration, which would cause no extra side effects in the database. It has two Navigation properties for convenience:

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
}

Now, if you have a nicely filled database set with ParentCategory records, you could query it in an action method as follows:

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);
}

This view would then take these top level categories as a model (I would strongly recommend creating a ViewModel for this), and use a Partial to render all children recursively:

@model IEnumerable<ProductCategory>

<table>
    @Html.Partial("CategoryRowPartial", Model)
</table>

Finally, the CategoryRowPartial, which also receives an IEnumerable<ProductCategory> would look like this. It calls itself recursively to display all children:

@model IEnumerable<ProductCategory>

@foreach (var category in Model)
{
    <tr><td>@category.Title</td></tr>
    @Html.Partial("CategoryRowPartial", category.Children)
}

Now, this doesn't take into account the level of each child nor the empty (and rather sloppy) td's & colspans. Personally, I'd use <ul> or <ol> for this. They are meant to be used to display hierarchies.

If you insist on using a <table>, I again recommend to create a specialized View Model which could hold the "depth" of each table row.



来源:https://stackoverflow.com/questions/47694651/recursion-in-a-table-using-razor-in-asp-net-core

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!