[英]MVC 3: HTML.DisplayFor and the Lambda expression
我找到了关于此的其他主题,但没有一个让我明白我想弄清楚的是什么。
我正在学习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>
我知道DisplayFor是HTML的扩展方法,它将表达式作为参数。 我研究了Lambda表达式并在其他上下文中理解它们,例如使用可枚举的字符串。 例如:
cities.Where(s => s.StartsWith("L"));
令我难以置信的是,在第二个例子中,表达式的第一部分实际上是在第二部分(s.startswith ..)中使用,所以它是有意义的,我得到程序用它做的事情。 但在MVC 3视图中并非如此。 modelItem不是在任何地方使用。 我尝试将“modelItem”重命名为任何类似的东西:
@Html.DisplayFor(iAmWearingShortPantsToday => item.Genre.Name)
此代码也可以正常工作,正确显示所有项目和值。 这使我怀疑在这种情况下“modelItem”实际上用于任何事情。 但那么,为什么呢?
我也尝试将这个Lambda表达式转换为委托(我认为它是简短形式),如下所示:
@(Html.DisplayFor(delegate(IEnumerable<MvcMusicStore.Models.Album> modelItem) { return item.Genre.Name; }))
但是,这不起作用。 产生的错误是:
CS1946:无法将匿名方法表达式转换为表达式树
因此我的问题是:
什么是“modelItem”有用? HTML.DisplayFor()对modelItem做了什么? 是否还有其他情况,表达的第一部分变得重要?
如果可以将此表达式转换为适当的委托,那么这也可以帮助我理解究竟发生了什么。
非常感谢
我理解你的困惑。 实际上,lambda表达式中从不使用modelItem
变量。 使用的是从外部上下文在闭包中捕获的item
变量。 item
变量只是foreach
循环中定义的局部变量。
顺便说一下,当你在ASP.NET MVC视图中看到类似于modelItem => item.Genre.Name
的表达式时,这通常是编码错误的一个标志。 躲开它。 互联网上充斥着这样糟糕的例子。 真。 我厌倦了看到这个。 请帮我根除这种做法。
这是实际使用变量的另一种方法:
@model IList<MvcMusicStore.Models.Album>
...
@for (var i = 0; i < Model.Count; i++) {
<tr>
<td>
@Html.DisplayFor(x => x[i].Genre.Name)
</td>
...
</tr>
}
甚至更好。 为什么要写循环呢? 当我们可以直接使用编辑/显示模板时:
@model IEnumerable<MvcMusicStore.Models.Album>
...
@Html.DisplayForModel()
然后定义一个显示模板,该模板将由ASP.NET MVC为模型集合的每个元素自动呈现( ~/Views/Shared/DisplayTemplates/Album.cshtml
)
@model Album
<tr>
<td>
@Html.DisplayFor(x => x.Genre.Name)
</td>
...
</tr>
我不确定我能回答你的问题,但是正确的部分用于告诉DisplayFor
哪个属性将为其创建显示。 它用于确定属性的类型(用于选择如何显示值)和值。
如果在TextBoxFor中使用它,它还用于检索属性的名称,因此文本框可以获得正确的名称。
我认为很多html-helper扩展方法中的表达式实际上有点奇怪,但它是让代码获取所有这些信息的简单方法,而不必将其作为字符串参数写下来(如果你改变了什么,没有给出编译时错误)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.