MVC剃刀@foreach


Answers:


162

关于@foreach的逻辑应该放在哪里的最佳实践是什么?

无处,就摆脱它。您可以使用编辑器或显示模板。

因此,例如:

@foreach (var item in Model.Foos)
{
    <div>@item.Bar</div>
}

可以完全由显示模板代替:

@Html.DisplayFor(x => x.Foos)

然后您将定义相应的显示模板(如果您不喜欢默认的显示模板)。因此,您将定义一个可重用的模板~/Views/Shared/DisplayTemplates/Foo.cshtml,该模板将由框架为Foos集合(IEnumerable<Foo> Foos { get; set; })的每个元素自动呈现:

@model Foo
<div>@Model.Bar</div>

显然,对于要显示一些输入字段以允许您编辑视图模型(而不是将其显示为只读)的情况,应使用编辑器模板完全相同的约定。


3
@DarinDimitrov是真的,如果您要使用其严格的MVC模型进行编码,但是如果出现某种情况,而该模型中没有需要循环收集的集合,则我看不到使用foreach的问题
Nicholas King

6
@NicholasKing,这种情况永远不会出现。除了控制器动作传递的视图模型中的视图之外,其他视图不应接触其他任何东西。如果它不在视图模型中,那么如果视图需要,则应将其放在其中。这正是视图模型的目的。
Darin Dimitrov

1
@MihaiLabo,是的,这就是我的意思。
Darin Dimitrov

2
如果集合中元素的类型不足以确定显示怎么办?例如,我的模型有一个字符串集合,但是有时候我想每行有一个字符串,而在另一种情况下,我希望它们之间用逗号分隔?
2014年

6
那么,到底是什么问题foreach呢?至少,显示模板(无论如何都是一种完全可接受的方法)都需要呈现一个新视图,这不是免费的。在大多数情况下,它不会显着影响您的网站加载时间,但是做得足够多,可能会导致性能下降。一foreach张望了一下HTML是并将永远是几乎瞬间。就像我说的,这不是一个巨大的交易无论哪种方式,虽然,但如果有的话有一个参数使用foreach
克里斯·普拉特

98

人们说不要将逻辑放在视图中时,通常是指业务逻辑,而不是呈现逻辑。以我的拙见,我认为在视图中使用@foreach完全可以。


22
同意 让我想起了古老的语义HTML辩论,最终导致人们尝试使用divs和CSS为实际的表格数据创建“表格”,因为它们是如此的反表格。
克里斯·普拉特

1
我同意。人类不善于误导。我是否真的需要一个具有新视图的新文件夹,只是为了在视图模型的列表中显示内容?
唐·奇德尔

1
创建响应式视图是否不需要使用div / css创建表格数据视图?
frostshoxx

13

我使用@foreach当我发送包含的实体的列表(例如,为了显示网格2在1个视图)的实体

例如,如果我要发送包含以下内容的实体Foo作为模型Foo1(List<Foo1>)Foo2(List<Foo2>)

我可以使用以下内容引用第一个列表:

@foreach (var item in Model.Foo.Foo1)
{
    @Html.DisplayFor(modelItem=> item.fooName)
}

11

对于我曾在剃刀视图中使用过foreach的情况,请回复@DarinDimitrov。

<li><label for="category">Category</label>
        <select id="category">
            <option value="0">All</option>
            @foreach(Category c in Model.Categories)
            {
                <option title="@c.Description" value="@c.CategoryID">@c.Name</option>
            }
        </select>
</li>

6
哇,您会在视图中这样写吗?为什么不编写Html.DropDownListFor只考虑标题的可重用的自定义助手呢?这很琐碎,不会将您的观点变成意大利面条代码:stackoverflow.com/a/7938038/29407
Darin Dimitrov 2012年

7
@DarinDimitrov是的,我们在非常敏捷的环境中工作,这意味着这种情况有时会阻止我们使用DropDownFor之类的东西,因为我们并不总是有明确定义的要求。我相信在这种情况下,下拉菜单最初并不需要“全部”,而是仅需要视图中的一个DropDown。由于此页面使用ajax来更新其严格的MVC模式,因此您无法根据要求将产品上载到所有类别。不是理想的,但有时是不可避免的。
尼古拉斯·金

也许更好的例子是使用此方法optgroup在选择列表中呈现元素,因为HtmlHelpers中不支持该元素。如果您只需要在选择列表中添加其他项目,则可以使用更好的方法来实现,然后仍然使用助手。
克里斯·普拉特

那不是我对敏捷的定义-我必须同意@DarinDimitrov
Luis Filipe

3

当使用重载指示模板时,答案将不起作用@Html.DisplayFor(x => x.Foos, "YourTemplateName)

似乎是这样设计的,请参见此案例。此外,框架给出的异常(关于类型未达到预期)非常令人误解,并且在第一次尝试时就愚弄了我(感谢@CodeCaster)

在这种情况下,您必须使用@foreach

@foreach (var item in Model.Foos)
{
    @Html.DisplayFor(x => item, "FooTemplate")
}

这个答案是由从事MVC的人写的,所以我想他们知道他们在说什么。MVC将迭代IEnumerable<T>T为每个元素的类型调用模板。
CodeCaster

关于您的编辑:是您的代码错误或该特定MVC版本中的错误(在5.2.2中适用于我)。它应该按已接受的答案中所述工作。不用说错了,而是根据需要打开有关该问题的自己的问题。
CodeCaster

@CodeCaster我相信我的答复增加了针对该特定情况的注意事项(浪费了我一些时间来找出问题所在)。能否请您添加一些说明,以保持投票立场?(感谢您的时间顺便说一句,只想
深入

我认为这不是一个很好的答案,因为它无法验证该错误,因此可以帮助“ A DisplayTemplate无法迭代”之类的谣言-应该这样做,因此应该可以工作。如果确实没有,请提交一个错误,然后打开一个单独的问题,在该问题上您可以重现该问题并提及该特定版本,而不是根据通常会发生的问题进行问答。
CodeCaster

@CodeCaster在了解我的具体情况之后,我又进行了一次编辑(我更改了整个文章)。在我上一次的编辑中,我指出了当接受的答案不适用于备份链接到由同一个人回答的相关问题的确切条件时的确切情况,这证明是设计使然而不是错误。
Tiberiu Craciun 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.