【问题标题】:Foreach in a Foreach in MVC ViewMVC 视图中的 Foreach 中的 Foreach
【发布时间】:2013-04-05 02:28:41
【问题描述】:

大编辑:我已经编辑了我的完整帖子,答案是我在 Von V 和 Johannes 的帮助下提出的,非常感谢你们!!!!

我一直在尝试在我的索引视图中的 foreach 循环内执行一个 foreach 循环,以在手风琴中显示我的产品。让我告诉你我是如何做到这一点的。

这是我的模型:

public class Product
{
    [Key]
    public int ID { get; set; }

    public int CategoryID { get; set; }

    public string Title { get; set; }

    public string Description { get; set; }

    public string Path { get; set; }

    public virtual Category Category { get; set; }
}

public class Category
{
    [Key]
    public int CategoryID { get; set; }

    public string Name { get; set; }

    public virtual ICollection<Product> Products { get; set; }
}

这是一个one-one一对多的关系,一个产品只有一个类别,但一个类别有很多产品。

在我看来,这是我想要做的事情:

@model IEnumerable<MyPersonalProject.Models.Product>   

    <div id="accordion1" style="text-align:justify">
    @foreach (var category in ViewBag.Categories)
    {
        <h3><u>@category.Name</u></h3>

        <div>

            @foreach (var product in Model)
            {
                if (product.CategoryID == category.CategoryID)
                {
                    <table cellpadding="5" cellspacing"5" style="border:1px solid black; width:100%;background-color:White;">
                        <thead>
                            <tr>
                                <th style="background-color:black; color:white;">
                                    @product.Title  
                                    @if (System.Web.Security.UrlAuthorizationModule.CheckUrlAccessForPrincipal("/admin", User, "GET"))
                                    {
                                        @Html.Raw(" - ")  
                                        @Html.ActionLink("Edit", "Edit", new { id = product.ID }, new { style = "background-color:black; color:white !important;" })
                                    }
                                </th>
                            </tr>
                        </thead>

                        <tbody>
                            <tr>
                                <td style="background-color:White;">
                                    @product.Description
                                </td>
                            </tr>
                        </tbody>      
                    </table>                       
                }
            }

        </div>
    }  
</div>

我不太确定这是正确的做法,但这正是我想要做的。对于每个类别,将该类别的所有产品放在一个折叠标签中。

  • 类别 1
    • 产品1
    • 产品 3
  • 2 类
    • 产品 2
    • 产品 4
  • 第 3 类
    • 产品5

在这里,我将为 我的一对一 一对多(感谢 Brian P)关系添加映射:

public class MyPersonalProjectContext : DbContext
{
    public DbSet<Product> Product { get; set; }
    public DbSet<Category> Category { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

        modelBuilder.Entity<Product>();
        modelBuilder.Entity<Category>();
    }
}

我还将添加我的控制器,以便您了解我是如何做到的:

public ActionResult Index()
    {
        ViewBag.Categories = db.Category.OrderBy(c => c.Name).ToList();
        return View(db.Product.Include(c => c.Category).ToList());
    }

大编辑:我已经编辑了我的完整帖子,答案是我在 Von V 和 Johannes 的帮助下提出的,非常感谢你们!!!!

【问题讨论】:

  • 如果存在一对一的关系,为什么 Product 类中有一个 ICollection?你的控制器动作是什么样的?传递给视图的模型是什么?
  • 我有 ICollection 的原因是因为有时我需要获取此模型的 CatogoryID 或名称。就像在这里一样,我想在我的手风琴

    上显示类别名称。我做得不对吗?

  • 你们的关系不是一对一,而是多对一,你只是倒着想。 1 个类别有很多产品。
  • @BrianP 我认为你是对的......我倒是想了一下。现在,为什么我无法做到这一点是有道理的

标签: c# asp.net asp.net-mvc entity-framework asp.net-mvc-4


【解决方案1】:

控制器

public ActionResult Index()
    {


        //you don't need to include the category bc it does it by itself
        //var model = db.Product.Include(c => c.Category).ToList()

        ViewBag.Categories = db.Category.OrderBy(c => c.Name).ToList();
        var model = db.Product.ToList()
        return View(model);
    }


查看

您需要过滤具有给定类别的模型

like :=> Model.where(p=>p.CategoryID == category.CategoryID)

试试这个...

@foreach (var category in ViewBag.Categories)
{
    <h3><u>@category.Name</u></h3>

    <div>

        @foreach (var product in Model.where(p=>p.CategoryID == category.CategoryID))
        {

                <table cellpadding="5" cellspacing"5" style="border:1px solid black; width:100%;background-color:White;">
                    <thead>
                        <tr>
                            <th style="background-color:black; color:white;">
                                @product.Title  
                                @if (System.Web.Security.UrlAuthorizationModule.CheckUrlAccessForPrincipal("/admin", User, "GET"))
                                {
                                    @Html.Raw(" - ")  
                                    @Html.ActionLink("Edit", "Edit", new { id = product.ID }, new { style = "background-color:black; color:white !important;" })
                                }
                            </th>
                        </tr>
                    </thead>

                    <tbody>
                        <tr>
                            <td style="background-color:White;">
                                @product.Description
                            </td>
                        </tr>
                    </tbody>      
                </table>                       
            }


    </div>
}  

【讨论】:

    【解决方案2】:

    假设你的控制器的动作方法是这样的:

    public ActionResult AllCategories(int id = 0)
    {
        return View(db.Categories.Include(p => p.Products).ToList());
    }
    

    修改你的模型如下:

    public class Product
    {
        [Key]
        public int ID { get; set; }
        public int CategoryID { get; set; }
        //new code
        public virtual Category Category { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
        public string Path { get; set; }
    
        //remove code below
        //public virtual ICollection<Category> Categories { get; set; }
    }
    
    public class Category
    {
        [Key]
        public int CategoryID { get; set; }
        public string Name { get; set; }
        //new code
        public virtual ICollection<Product> Products{ get; set; }
    }
    

    那么从现在开始,控制器将类别作为模型(而不是产品):

    foreach (var category in Model)
    {
        <h3><u>@category.Name</u></h3>
        <div>
            <ul>    
                @foreach (var product in Model.Products)
                {
                    // cut for brevity, need to add back more code from original
                    <li>@product.Title</li>
                }
            </ul>
        </div>
    }
    

    更新:将 ToList() 添加到控制器返回语句。

    【讨论】:

    • 如果我去做这样的事情,这似乎很不错。我将不得不修改我的映射。让我用我的映射更新我的代码,以便您对其发表评论。
    • 对我的映射有什么想法吗?
    • 你的映射对我来说似乎落后了,因为它是一个类别可以有很多产品,每个产品只能有一个类别。我建议纠正你的映射。为什么要创建自定义映射而不是使用默认的 EF 映射?
    • 以为我必须指定它。如果它可以以这种方式解决,我不会根据我的个人知识对其进行修改。但是我的问题 ATM 是当我尝试调用我的第一个 foreach 循环时,它总是说我不能这样做,因为 Model.Category 没有 get enumerator。
    • 如果您按照我的示例进行操作 - 不需要自定义映射,Category 是作为属性或产品的单个对象(不是集合)。请记住,控制器操作返回类别(不是产品)的集合。
    【解决方案3】:

    你有:

    foreach (var category in Model.Categories)
    

    然后

    @foreach (var product in Model)
    

    基于该视图和模型,Model 的类型似乎为 Product,如果是,则第二个 foreach 无效。实际上,如果您返回 Product 的集合,则第一个可能是无效的。

    更新:

    你是对的,我返回的是 Product 类型的模型。另外,我愿意 既然您已经指出了问题,那就了解什么是错误的。我怎么样 如果我不能这样做,应该做我想做的事吗?

    当您说要返回 Product 类型的模型时,我很惊讶您的代码编译。你可以这样做:

    @foreach (var category in Model)
    {
        <h3><u>@category.Name</u></h3>
    
        <div>
            <ul>    
                @foreach (var product in category.Products)
                {
                    <li>
                        put the rest of your code
                    </li>
                }
            </ul>
        </div>
    }
    

    这表明您不要返回Product,而是返回Category 与产品 的集合。在 EF 中是这样的:

    // I am typing it here directly 
    // so I'm not sure if this is the correct syntax.
    // I assume you know how to do this,
    // anyway this should give you an idea.
    context.Categories.Include(o=>o.Product)
    

    【讨论】:

    • 现在应该可以了,你说得对,我返回的是 Product 类型的模型。另外,既然您已经指出了,我确实明白出了什么问题。如果我不能这样做,我应该怎么做我想做的事?
    • 好吧,我想要你的答案。让我帮你解决这个问题。
    • 唯一不适合我的是我的映射,不确定它是否正确。否则,按照您的操作方式,它会起作用。
    • 感谢您的帮助,我以某种方式做到了。用我的解决方案编辑了我的帖子,你怎么看?
    【解决方案4】:

    试试这个:

    看起来你每次都在循环每个产品,现在这是在循环每个与当前循环的类别具有相同类别 ID 的产品

    <div id="accordion1" style="text-align:justify">
    @using (Html.BeginForm())
    {
        foreach (var category in Model.Categories)
        {
            <h3><u>@category.Name</u></h3>
    
            <div>
                <ul>    
                    @foreach (var product in Model.Product.Where(m=> m.CategoryID= category.CategoryID)
                    {
                        <li>
                            @product.Title
                            @if (System.Web.Security.UrlAuthorizationModule.CheckUrlAccessForPrincipal("/admin", User, "GET"))
                            {
                                @Html.Raw(" - ")  
                                @Html.ActionLink("Edit", "Edit", new { id = product.ID })
                            }
                            <ul>
                                <li>
                                    @product.Description
                                </li>
                            </ul>
                        </li>
                    }
                </ul>
            </div>
        }
    }  
    

    【讨论】:

    • 我不久前尝试过这样的事情,但是如果我做模特的话,对我来说。 => 我能访问的只是我的 Product 模型的值。我不能选择 Model.Product。
    猜你喜欢
    • 1970-01-01
    • 2013-04-14
    • 2012-02-12
    • 2014-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-06
    相关资源
    最近更新 更多