模型如下:
public class User
{
[DisplayName("ID")]
[Range(0, 9999)]
public int ID { get; set; }
public string Mask { get; set; }
}
然后控制器返回上述模型的IQueryable
有两种观点。父视图,然后是部分视图,它从模型
中呈现每一行主视图
@model IQueryable<User>
@{
var Array = Model.ToArray();
}
//Header here
<tbody id="table-body-vlan">
@{
for (var i = 0; i < Array.Length; i++)
{
Html.RenderPartial("_AddRow", Array [i], new ViewDataDictionary() { { "Index", i } });
}
}
</tbody>
</table>
</div>
}
**然后局部查看**
@model User
@{
var index = ViewData["Index "];
}
<tr class="js-deletable-item" id="row-@index" data-id="@Model.ID" >
<td class="editable">
@Html.TextBoxFor(v => Model.ID, new {Name = "ID[" + index + "]", id = "id-" + Model.ID, Value = Model. ID > 0 ? Model. ID.ToString() : ""})
</td>
<td class="editable">
@Html.TextBoxFor(v => Model.Name, new {Name = "Id[" + index + "].Name", data_val = "false" })
</td>
</tr>
问题如下: 如果IQueryable中有10条记录,则客户端验证仅适用于第一行。
e.g。如果我在第一行为ID字段键入101S,则会收到无效ID的警告(通过更改背景颜色)。 但是如果我对第二行或其他行做同样的事情,那么我看不到背景颜色的变化。客户端验证(通过数据注释定义)仅适用于第一行。
我想在第一行渲染之后,它没有将那些与Annotation相关的属性添加到其他行。
答案 0 :(得分:0)
我建议你看看MVC中的Editor and Display Templates:
在此处创建一个编辑器模板:~/Views/Shared/EditorTemplates/User.cshtml
,如下所示:
@model User
<tr class="js-deletable-item">
<td class="editable">
@Html.TextBoxFor(m => m.Id)
</td>
<td class="editable">
@Html.TextBoxFor(m => m.Name)
</td>
</tr>
每当您致电EditorForModel
时,都会自动为模型的每个元素呈现此内容。
在您的控制器中,在发送到视图之前,在.ToList()
对象上执行IQueryable<User>()
。
在主视图中:
@model IEnumerable<User>
<table>
<thead>
<tr>
<td>Id</td>
<td>Name</td>
</tr>
</thead>
<tbody>
@Html.EditorForModel()
</tbody>
</table>
更简单,更清洁吧?但使用这些模板的主要优点是,它们将自动创建适当的name
属性。类似的东西:
<input data-val="true" name="[0].Id" value="" />
<span class="text-danger field-validation-valid" data-valmsg-for="[0].ID"></span>
每一行都会获得一个唯一的name
属性。在您的代码中,您的所有行都具有相同的name="ID"
和data-valmsg-for="ID"
。因此,只有第一行得到验证。
在提交包含name
的表单时,collections
属性也很重要。否则,当您提交(Refer)时,用户列表将以null
结束。
如果您不想使用EditorTemplates
,则必须执行for
循环(不是foreach
)并填充行。