简短的回答是肯定的——必须有一个模型作为参数传递给 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 进行选择,那会很有趣。