【问题标题】:MVC 3: HTML.DisplayFor and the Lambda expressionMVC 3:HTML.DisplayFor 和 Lambda 表达式
【发布时间】:2012-07-26 03:26:27
【问题描述】:

我找到了与此相关的其他主题,但没有一个能让我理解我想要弄清楚的内容。

我正在研究 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) 的第一部分实际上在第二部分 (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 有什么作用?是否还有其他情况,表达式的第一部分变得重要?

如果可以将此表达式转换为适当的委托,那也可能有助于我理解到底发生了什么。

非常感谢

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-3


    【解决方案1】:

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

    顺便说一句,当您在 ASP.NET MVC 视图中看到像 modelItem =&gt; 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>
    

    【讨论】:

    • 您使用for而不是foreach循环的任何特殊原因?
    • 是的,特别的原因是 StackOverflow 上有数百万个问题,使用 foreach 和其中的输入字段,如 @Html.TextBoxFor(modelItem =&gt; item.Name) 并询问为什么 POST 操作没有返回任何值。为什么模型总是为空。你知道为什么吗?
    • 1:你说 modelItem => item.Genre.Name 是不好的做法。但这正是默认 MVC 3 脚手架的结果。这怎么可能是不好的做法?它也在我正在阅读的书中,Wrox 的 Professional MVC 3。 2:那么如果没有使用modelItem,为什么会有呢?你有理论吗?
    • 不好的做法。这是我的理论:-) 不要使用它。请改用编辑器/显示模板。每天我都必须回答有关人们对此有问题的问题。这是我今天回答的一个:stackoverflow.com/a/11682510/29407。 OP使用与您完全相同的代码。并且相信,这个过程每天都在重复,我已经厌倦了。你不相信这是不好的做法吗?那就是你自己的问题了。在这种情况下可以随意使用它,但是当您以后遇到模型绑定问题时,请记住您过去提出的这个问题 :-)
    • 在您的示例中,您使用的是显示模板 (DisplayFor),所以这并不重要。但是,不知不觉中,您开始将这个 foreach 概念适应 EditorTemplates,而这正是您的问题开始的时候。
    【解决方案2】:

    不确定我能否回答您的问题,但正确的部分用于告诉DisplayFor 哪个属性将为哪个属性创建显示。它用于确定属性的类型(用于选择如何显示值)和值。

    如果在 TextBoxFor 中使用,它也用于检索属性的名称,因此文本框可以获得正确的名称。

    我认为很多 html-helper 扩展方法中的表达式实际上有点奇怪,但这是让代码获取所有这些信息的简单方法,而无需将其写为字符串参数(即如果你改变任何东西都会失败,而不给出编译时错误)。

    【讨论】:

      猜你喜欢
      • 2012-04-23
      • 2011-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-09
      • 2016-01-17
      • 1970-01-01
      相关资源
      最近更新 更多