我有一个视图,用户可以通过选择checkboxex选择任意数量的俱乐部。俱乐部是主要模型的属性,类型为列表<ClubModel
&gt;。
在重构的过程中,我从这开始:
@using (Html.BeginForm())
{
<fieldset>
<legend>Voor Select clubs </legend><br />
<table>
<tr>
@for (var i = 0; i < Model.Clubs.Count; i++)
{
if (i % 3 == 0)
{
@:</tr><tr>
}
<td>
@Html.HiddenFor(model => model.Clubs[i].ClubID)
@Html.EditorFor(model => model.Clubs[i].IsAvailable)
</td>
<td>@Html.DisplayFor(model => model.Clubs[i].ClubName)</td>
}
</tr>
</table>
<input type="submit" value="Submit" />
</fieldset>
}
这样可以正常工作:使用填充的Clubs属性返回模型。
现在我取出<td
&gt;标记并将它们移动到EditorTemplate:
@using (Html.BeginForm())
{
<fieldset>
<legend>Select Clubs </legend><br />
<table>
<tr>
@for (var i = 0; i < Model.Clubs.Count; i++)
{
if (i % 3 == 0)
{
@:</tr><tr>
}
@Html.EditorFor(model=>model.Clubs[i])
}
</tr>
</table>
<input type="submit" value="Submit" />
</fieldset>
}
这仍然有效(模板未显示)。
现在我想将循环移动到EditorTemplate:
@using (Html.BeginForm())
{
<fieldset>
<legend> Select Clubs</legend><br />
<EditorFor(model=>model.Clubs,"ListOfClubs")
<input type="submit" value="Submit" />
</fieldset>
}
我正式创建一个名为'ListOfClubs'的EditorTemplate:
@using InvallersManagementMVC3.ViewModels;
@model List<StandInClubModel>
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<table>
<tr>
@for (var i = 0; i < Model.Count; i++)
{
if (i % 3 == 0)
{
@:</tr><tr>
}
<td>
@Html.HiddenFor(model => model[i].ClubID)
@Html.EditorFor(model => model[i].IsAvailable)
</td>
<td>@Html.DisplayFor(model => model[i].ClubName)</td>
}
</tr>
</table>
</body>
</html>
这会正确显示带有IsAvailable属性复选框的分会,但现在发布模型的Clubs属性为空!
我哪里错了?
编辑: 我尝试使用以下方法实现Cymen的答案:
@Html.EditorFor(model=>model.Clubs,"ClubModel")
或在传入这些元素的列表时指定elementtemplate。但是有一个例外,我受到了欢迎: 用户代码未处理System.InvalidOperationException Message =传递到字典中的模型项的类型为'System.Collections.Generic.List`1 [InvallersManagementMVC3.ViewModels.ClubModel]',但此字典需要类型为'InvallersManagementMVC3.ViewModels.ClubModel'的模型项。
答案 0 :(得分:7)
您似乎正在尝试将传递给视图的模型列表分组3.因此,为了重构您的代码,我建议您首先引入正确的视图模型=&gt;反映这一特定观点要求的一个:
public class GroupedClubs
{
public IEnumerable<StandInClubModel> Clubs { get; set; }
}
现在在控制器操作中,我们应该简单地将域模型转换为此视图模型的列表:
public ActionResult Index()
{
// This is our domain model. In a real world application
// it would come from a service layer. I am hardcoding some
// values here for simplicity
var clubs = Enumerable.Range(1, 8).Select(x => new StandInClubModel
{
ClubID = x,
ClubName = "club " + x
});
// Now we group the list of clubs by 3 in order to simplify
// our view code and avoid writing some ugly loops and spaghetti code
// In a real world application I would recommend externalizing this mapping
// between the domain model and the view model into a separate mapping layer
// AutoMapper is great for this job
var viewModel = clubs
.Select((club, index) => new { club, index })
.GroupBy(g => g.index / 3, i => i.club)
.Select(x => new GroupedClubs
{
Clubs = x
});
return View(viewModel);
}
现在剩下的就是写一些观点:
~/Views/Home/Index.cshtml
:
@model IEnumerable<GroupedClubs>
@using (Html.BeginForm())
{
<fieldset>
<legend> Select Clubs</legend>
<br />
<table>
<tbody>
@Html.EditorForModel()
</tbody>
</table>
<input type="submit" value="Submit" />
</fieldset>
}
~/Views/Home/EditorTemplates/GroupedClubs.cshtml
:
@model GroupedClubs
<tr>
@Html.EditorFor(x => x.Clubs)
</tr>
~/Views/Home/EditorTemplates/StandInClubModel.cshtml
:
@model StandInClubModel
<td>
@Html.HiddenFor(x => x.ClubID)
@Html.EditorFor(x => x.IsAvailable)
</td>
<td>
@Html.DisplayFor(x => x.ClubName)
</td>
这就是全部。现在你可以有一个控制器动作来处理表单提交:
[HttpPost]
public ActionResult Index(List<GroupedClubs> clubs)
{
... map the view model back to some domain model and pass
to the service layer for processing
}
答案 1 :(得分:3)
制作一个编辑器,用于ClubModel的一个实例,让ASP.NET MVC渲染它(让它进行迭代)。 ASP.NET MVC对输入标记有一些特定的命名/ id方案,你不会在迭代中渲染它们。
所以使用它 - 与你的相同,但要观察模板名称:
@using (Html.BeginForm())
{
<fieldset>
<legend>Select Clubs</legend><br />
<table>
<%: EditorFor(model=>model.Clubs, "Club") %>
</table>
<input type="submit" value="Submit" />
</fieldset>
}
和EditorFor。请注意,即使您传入上面的列表,它也适用于模型的单个实例。这是ASP.NET MVC的“魔力”。
<tr>
<td>
@Html.HiddenFor(model => model.ClubID)
@Html.EditorFor(model => model.IsAvailable)
</td>
<td>@Html.DisplayFor(model => model.ClubName)</td>
</tr>