【问题标题】:Child foreach not looping as intended in Partial using ViewModel使用 ViewModel 的子 foreach 未按预期循环
【发布时间】:2013-12-25 22:18:33
【问题描述】:

我有一个食谱列表,每个食谱都有许多食谱行,我想循环每个食谱及其对应的食谱行 foreach 在父食谱 foreach 内循环。

食谱课

    namespace XXX.Models
    {
        public class Recipe
        {
            public int RecipeID { get; set; }
            public string RecipeName { get; set; }
            public string RecipeInstructions { get; set; }

            public virtual List<RecipeLine> RecipeLines { get; set; }
        }
    }

RecipeLine 类

    namespace XXX.Models
    {
        public class RecipeLine
        {
            public int RecipeLineID { get; set; }
            public float Quantity { get; set; }

            public int MeasurementID { get; set; }
            public int RecipeID { get; set; }
            public int IngredientID { get; set; }

            public virtual Measurement Measurement { get; set; }
            public virtual Recipe Recipe { get; set; }
            public virtual Ingredient Ingredient { get; set; }

        }
    }

不需要列出成分和测量类,但它们的结构很好。

现在让我们看看 ViewModel

    namespace XXX.ViewModels
    {
        public class RecipeLineViewModel
        {
            public IEnumerable<Recipe> Recipes { get; set; }
            public IEnumerable<RecipeLine> RecipeLines { get; set; }
        }
    }

还有 PartialsController

    namespace XXX.Controllers
    {

        public class PartialsController : Controller
        {
            private XXXDb db = new XXXDb();

            public ActionResult RecipeList()
            {
                RecipeLineViewModel viewModel;

                viewModel = new RecipeLineViewModel();
                viewModel.Recipes = db.Recipes.ToList();
                viewModel.RecipeLines = db.RecipeLines.Include(r => 
                r.Measurement).Include(r => r.Ingredient);

                return PartialView("_RecipeList", viewModel);
            }
        }
    }

现在局部视图是 Views > Partials > __RecipeList.cshtml

配方列表部分视图

    @model XXX.ViewModels.RecipeLineViewModel

    @foreach (Recipe recipe in Model.Recipes) 
        {
        <div>@recipe.RecipeName</div>
        <div>@recipe.RecipeInstructions</div>

            foreach (RecipeLine recipeLines in Model.RecipeLines)
            {
                <div class="row">
                    <div class="large-12 columns">
                        @recipeLines.Quantity @recipeLines.Measurement.MeasurementEn 
                        @recipeLines.Ingredient.IngredientNameEn
                    </div>
                </div>
            }

        }
    }

(我在每个 recipeLine 的末尾打印了 RecipeID,以表明每个食谱都在重复 RecipeID = 1 的食谱行,而不是与他们自己的 RecipeID 相关的行。我是这个东西的新手,我是假设我应该在某个地方告诉食谱行他们应该循环的 RecipeID ????

这是我得到的结果:

【问题讨论】:

  • 如果你的Recipe 类有一个RecipeLines 集合,为什么你的ViewModel 中有一个?你的内部循环应该打印recipe.RecipeLines...
  • 我正在尝试修复错误。

标签: c# asp.net-mvc foreach viewmodel partials


【解决方案1】:

在您的Recipie 模型中,您有一个List&lt;RecipieLine&gt; 属性,可以假设它是维护一个或多个RecipieLine 模型对象。在您的 RecipieLineViewModel 中,您有两个单独的 IEnumerable 集合,暴露了您的 RecipieRecipieLine 对象。

在您的实际视图中,您正在迭代您的 Recipie 集合:

@foreach (Recipe recipe in Model.Recipes)

看起来不错,但是,以下行是您的问题:

foreach (RecipeLine recipeLines in Model.RecipeLines)

这会枚举存储在您的RecipieLineViewModelRecipieLine 集合中的RecipieLine 模型对象,但是,它目前无法知道您当前在外部foreach 中枚举的是哪个Recipie

您要么希望使用当前Recipie 对象枚举中可用的数据提供某种where LINQ 子句,要么更改内部foreach 以使用当前Recipie 枚举而不是Model.

更新

为了完整起见,下面是一个示例,说明如何使用当前的Recipe 对象枚举来访问其关联的RecipieLines:

@forech (var recipie in Model.Recipies)
{
    <div>@recipe.RecipeName</div>
    <div>@recipe.RecipeInstructions</div>
    foreach (var recipieLine in recipie.RecipieLines)
    {
        <div class="row">
            <div class="large-12 columns">
                // Do something with recipieLine here
            </div>
        </div>
    }
}

上述方法是我的首选方法,因为每次枚举执行 LINQ 查询效率更高,并从您的ViewModel 中删除IEnumerable&lt;RecipieLine&gt;,这实际上是重复代码。

【讨论】:

  • 感谢您的回答,我选择了上面的答案作为正确答案,因为他提供了一个有效的代码示例;但是,我给你的答案是 1up,因为解释会导致正确的答案,另外你提供了一个我会研究的替代选项。感谢您花时间回复!
  • @EricB - 很高兴你得到了答案,这是优先事项,尽管如此,我们还是很感谢你的支持。使用当前Recipie 枚举的替代解决方案将允许您删除ViewModel 中重复的IEnumerable&lt;RecipieLine&gt; 集合。这将是我的首选方法。
  • 第二次foreach:foreach(recipeLine recipeLine in recipe.RecipeLines)
  • @aershov - 我想你的意思是把你的评论贴在好友上面。
  • 感谢我现在倾注于此。你们是一个巨大的帮助。我真的很想知道正确的方法。
【解决方案2】:

在 foreach 中添加 where Linq 子句。

   @foreach (Recipe recipe in Model.Recipes) 
            {
            <div>@recipe.RecipeName</div>
            <div>@recipe.RecipeInstructions</div>

                foreach (RecipeLine recipeLines in Model.RecipeLines.Where(rl => rl.RecipeID == recipe.RecipeID))
                {

更新:
你也可以在 Recipes 中明确地包含 RecipeLine 的东西,你根本不需要 RecipeLine Collection!只需遍历 recipe.RecipeLines

类似这样的:

viewModel.Recipes = db.Recipes.Include("RecipeLine").Include("RecipeLine.Measurement").
                .Include("RecipeLine.Ingredient");

【讨论】:

  • 感谢您的代码示例,这正是我想要做的,但我的语法不正确。谢谢你的时间!由于代码示例有效(剪切和粘贴),我将您标记为正确答案。
  • 自从我 1up 你并选择它作为正确答案你得到 25 分!现在你可以评论人们的答案,因为我给你超过 50 分!我想你现在也可以上传图片了,因为你已经超过 40 点了。干得好,谢谢你的回答!
  • 感谢您的替代。该示例中是否有任何优化?是否会减少服务器/数据库上的工作量?我确实喜欢我拥有它的方式,因为我只是在学习 Partials 和 View Models,而且它非常冗长,这让我很容易阅读和理解,但我也喜欢学习捷径,它需要更少的代码和效率访问数据库、服务器等。
  • 嗯,谢谢)第一种方法较慢,因为,例如,如果您有 10 个食谱和 100 个 recipeLines,它将遍历所有 100 个食谱行 10 次(对于每个 where)每次寻找特定的 RecipeID .而在第二种方法中,您只会获得每个食谱的食谱集合,并且您不需要在“哪里”执行 10 次,并且您的 ViewModel 中不需要 IEnumerable
  • 顺便说一下,在您当前的代码中 .Include(r => r.Recipe) 是多余的。
猜你喜欢
  • 2021-10-06
  • 1970-01-01
  • 1970-01-01
  • 2016-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-06
  • 1970-01-01
相关资源
最近更新 更多