快速刷新。
什么时候:
模型具有类型的属性 IEnumerable<T>
您将此属性传递给Html.EditorFor()使用仅接受lambda表达式的重载
您T在Views / Shared / EditorTemplates下具有该类型的编辑器模板
然后MVC引擎将自动为可枚举序列中的每个项目调用编辑器模板,并生成结果列表。
例如,当存在一个Order具有property 的模型类时Lines:
public class Order
{
public IEnumerable<OrderLine> Lines { get; set; }
}
public class OrderLine
{
public string Prop1 { get; set; }
public int Prop2 { get; set; }
}
并且有一个视图Views / Shared / EditorTemplates / OrderLine.cshtml:
@model TestEditorFor.Models.OrderLine
@Html.EditorFor(m => m.Prop1)
@Html.EditorFor(m => m.Prop2)
然后,当您@Html.EditorFor(m => m.Lines)从顶层视图调用时,您将获得一个页面,其中包含每个订单行的文本框,而不仅仅是一个。
但是,正如您在链接的问题中看到的那样,这仅在您使用的特定重载时才有效EditorFor。如果提供模板名称(为了使用未在OrderLine类后命名的模板),则不会发生自动序列处理,而是会发生运行时错误。
此时,您将必须将自定义模板的模型声明为,IEnumebrable<OrderLine>并以某种方式手动遍历其项目以输出所有项目,例如
@foreach (var line in Model.Lines) {
@Html.EditorFor(m => line)
}
这就是问题开始的地方。
以这种方式生成的HTML控件均具有相同的ID和名称。当您稍后对其进行POST时,模型绑定程序将无法构造OrderLines 的数组,而您在控制器的HttpPost方法中获得的模型对象将为null。
如果看一下lambda表达式,这是有道理的-它实际上并没有将正在构造的对象链接到它所来自的模型中的某个位置。
我尝试了各种遍历项目的方法,似乎唯一的方法是将模板的模型重新声明为,IList<T>并使用进行枚举for:
@model IList<OrderLine>
@for (int i = 0; i < Model.Count(); i++)
{
@Html.EditorFor(m => m[i].Prop1)
@Html.EditorFor(m => m[i].Prop2)
}
然后在顶级视图中:
@model TestEditorFor.Models.Order
@using (Html.BeginForm()) {
@Html.EditorFor(m => m.Lines, "CustomTemplateName")
}
它提供了正确命名的HTML控件,这些模型控件可以在提交时由模型绑定程序正确识别。
虽然这样做有效,但感觉却很不对劲。
使用带有的自定义编辑器模板的正确,惯用方式是什么EditorFor,同时保留所有允许引擎生成适合于模型绑定器的HTML的逻辑链接?
DIEA