4

表达式何时传递给DisplayForEditorFor需要使用模型进行数据访问?

例如,我可能有以下模型

class MyModel {
   IList<SubModel> Subs { get; set; }
}
class SubModel {
   string Name { get; set; }
}

然后我可以使用从模型开始的完整路径来编写我的视图数据访问:

@Html.DisplayFor(m => m.Subs[i].Name)

或者,我可能在不使用模型的视图中有这样的东西:

@foreach (var item in Model.Subs) {
    @Html.DisplayFor(m => item.Name)
}

但在上面我实际上并没有使用该模型。这似乎每次我都尝试过,但在什么情况下我可能会遇到问题?

EditorFor通常使用 将Expression名称/ID 构建到表单元素中。在指定传递给的表达式时不使用模型是否安全EditorFor

4

1 回答 1

1

简短的回答是肯定的——必须有一个模型作为参数传递给 lambda 方法。如果您的 View 没有模型并且您调用 DisplayFor 或 EditorFor,您将看到错误消息“模板只能用于字段访问、属性访问、单维数组索引或单参数自定义索引器表达式。”

因此,您必须有一个模型才能使用 DisplayFor,但实际上您不必使用它。例如,您可以这样做:

Html.EditorFor(m => i)

在这种情况下,Html 名称和 id 都将是“i”。

但是有一些注意事项需要注意。您可能希望为 SubModel 创建一个强类型的局部视图,例如,在 Shared/Display Templates 或 Editor Templates 文件夹中。在这种情况下,您可以将 foreach 与 DisplayFor 一起使用。

如果您使用 EditorFor 并且希望发布的字段绑定回模型,则需要使用:

for (i = 0; ...)

而不是 foreach,以便您的 Html 表单字段以可绑定的名称结束,例如 Subs[1].Name。如果您使用 foreach,您的所有输入都将具有相同的名称和 ID,例如:

id="s_Name" name="s.Name" 

而使用 for 循环,您会得到:

id="SubModels_0__Name" name="SubModels[0].Name"

for 循环生成合法的 html(唯一 id),并且可以重新绑定到服务器上的列表。

澄清一下:当您使用 EditorFor 或 DisplayFor 时,需要注意两件事。首先,您传入的表达式决定了用于 Html 元素的字段名称。如果表达式与您的模型相关,则名称源自模型,如上例所示。因此,如果我绑定到模型上的子类:

Html.DisplayFor(m => m.Submodel.Name)

Html 字段名称将是“Submodel.Name”,它将在回发时重新绑定到相同的层次结构(请注意,您也可以使用重载方法之一自己设置名称)。

第二个方面是您的表达式是类型化的(也就是说,它解析为 CLR 类型或您的自定义类型之一)。为了呈现该类型,MVC 会查找其模型匹配的模板。它使用从当前 View 文件夹开始的路径层次结构查找其模板,然后是 Shared 文件夹,如果找不到自定义模板,它会回退到其内部模板。

所以你需要考虑这两个来实现你想要的渲染和回发绑定。但是,如果您只对显示数据感兴趣,则不必担心 Html 字段名称与您的模型匹配,您可以使用任意名称或根本不使用任何名称,让 MVC 生成它们。但是您也应该知道,Html id 应该是唯一的,并且在上面的 foreach 示例中,您最终可以得到相同的 id。当前的浏览器似乎对此没有问题,但是如果您想使用 Javascript 通过 id 进行选择,那会很有趣。

于 2012-06-07T08:38:19.567 回答