MVC 3:HTML.DisplayFor和Lambda表达式

Ale*_*ner 5 c# asp.net-mvc asp.net-mvc-3

我找到了关于此的其他主题,但没有一个让我明白我想弄清楚的是什么.

我正在学习MVC 3,我在使用脚手架模板中的@HTML.DisplayFor()处理Lambda表达式时遇到了问题.

我正在使用MvcMusicStore示例应用程序,脚手架创建的视图如下所示:

@model IEnumerable<MvcMusicStore.Models.Album>

...

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Genre.Name)
        </td>
Run Code Online (Sandbox Code Playgroud)

我知道DisplayFor是HTML的扩展方法,它将表达式作为参数.我研究了Lambda表达式并在其他上下文中理解它们,例如使用可枚举的字符串.例如:

cities.Where(s => s.StartsWith("L"));
Run Code Online (Sandbox Code Playgroud)

令我难以置信的是,在第二个例子中,表达式的第一部分实际上是在第二部分(s.startswith ..)中使用,所以它是有意义的,我得到程序用它做的事情.但在MVC 3视图中并非如此.modelItem不是在任何地方使用.我尝试将"modelItem"重命名为任何类似的东西:

@Html.DisplayFor(iAmWearingShortPantsToday => item.Genre.Name)
Run Code Online (Sandbox Code Playgroud)

此代码也可以正常工作,正确显示所有项目和值.这使我怀疑在这种情况下"modelItem"实际上用于任何事情.但那么,为什么呢?

我也尝试将这个Lambda表达式转换为委托(我认为它是简短形式),如下所示:

@(Html.DisplayFor(delegate(IEnumerable<MvcMusicStore.Models.Album> modelItem) { return item.Genre.Name; }))
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用.产生的错误是:

CS1946:无法将匿名方法表达式转换为表达式树

因此我的问题是:

什么是"modelItem"有用?HTML.DisplayFor()对modelItem做了什么?是否还有其他情况,表达的第一部分变得重要?

如果可以将此表达式转换为适当的委托,那么这也可以帮助我理解究竟发生了什么.

非常感谢

Dar*_*rov 2

我理解你的困惑。实际上,modelItemlambda 表达式中从未使用变量。使用的是item从外部上下文的闭包中捕获的变量。该item变量只是foreach循环中定义的局部变量。

顺便说一句,当您modelItem => item.Genre.Name在 ASP.NET MVC 视图中看到类似表达式时,这通常是不良编码实践的标志。躲开它。互联网上充斥着这样的坏例子。真的。我厌倦了看到这个。请帮助我根除这种做法。

这是实际使用变量的另一种方法:

@model IList<MvcMusicStore.Models.Album>
...

@for (var i = 0; i < Model.Count; i++) {
    <tr>
        <td>
            @Html.DisplayFor(x => x[i].Genre.Name)
        </td>
        ...
    </tr>
}
Run Code Online (Sandbox Code Playgroud)

甚至更好。为什么要写循环呢?当我们可以直接使用编辑器/显示模板时:

@model IEnumerable<MvcMusicStore.Models.Album>
...
@Html.DisplayForModel()
Run Code Online (Sandbox Code Playgroud)

然后定义一个显示模板,该模板将由 ASP.NET MVC 自动为模型集合的每个元素呈现 ( ~/Views/Shared/DisplayTemplates/Album.cshtml)

@model Album
<tr>
    <td>
        @Html.DisplayFor(x => x.Genre.Name)
    </td>
    ...
</tr>
Run Code Online (Sandbox Code Playgroud)