抱歉,是否曾经有人问过?有一千种方法来表达它,所以事实证明寻找答案很困难。
我有一个具有以下属性的viewmodel:
public class AssignSoftwareLicenseViewModel
{
public int LicenseId { get; set; }
public ICollection<SelectableDeviceViewModel> Devices { get; set; }
}
SelectableDeviceViewModel的简化版本为:
public class SelectableDeviceViewModel
{
public int DeviceInstanceId { get; set; }
public bool IsSelected { get; set; }
public string Name { get; set; }
}
在我的视图中,我试图在输入表单中显示“设备”属性的可编辑复选框的列表。
目前,我的视图如下所示:
@using (Html.BeginForm())
{
@Html.HiddenFor(x => Model.LicenseId)
<table>
<tr>
<th>Name</th>
<th></th>
</tr>
@foreach (SelectableDeviceViewModel device in Model.Devices)
{
@Html.HiddenFor(x => device.DeviceInstanceId)
<tr>
<td>@Html.CheckBoxFor(x => device.IsSelected)</td>
<td>@device.Name</td>
</tr>
}
</table>
<input type="submit" value="Assign" />
}
问题是,当模型发布回控制器时,设备为空。
我的假设是发生这种情况,因为即使我在编辑其内容,也不会在窗体中明确包含Devices属性。我尝试将其包含在HiddenFor中,但这只是导致该模型的列表为空而不是null。
知道我在做什么错吗?
最佳答案
我的假设是这种情况正在发生,因为即使我
编辑其内容时,从不会显式显示Devices属性
包含在表格中。
不,您的假设是错误的。绑定不正确的原因是您的输入字段名称不正确。例如,它们被称为name="IsSelected"
而不是name="Devices[0].IsSelected"
。查看需要用于绑定到集合的正确有线格式:http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
但是为什么会这样呢?
这是因为您在视图中使用了foreach
循环。您使用x => device.IsSelected
作为该复选框的lambda表达式,但这根本没有考虑Devices属性(如通过查看网页的生成源代码可以看到的)。
所以我该怎么做?
我个人建议您使用编辑器模板,因为它们尊重复杂属性的导航上下文并生成正确的输入名称。因此,摆脱掉视图中的整个foreach
循环,并用一行代码替换它:
@Html.EditorFor(x => x.Devices)
现在定义一个自定义编辑器模板,该模板将由ASP.NET MVC自动为Devices集合的每个元素呈现。警告:此模板的位置和名称非常重要,因为按照惯例,它可以正常工作:
~/Views/Shared/EditorTemplates/SelectableDeviceViewModel.cshtml
:@model SelectableDeviceViewModel
@Html.HiddenFor(x => x.DeviceInstanceId)
<tr>
<td>@Html.CheckBoxFor(x => x.IsSelected)</td>
<td>@Html.DisplayFor(x => x.Name)</td>
</tr>
另一种方法(我不推荐)是将视图模型中的当前
ICollection
更改为索引集合(例如IList<T>
或数组T[]
):public class AssignSoftwareLicenseViewModel
{
public int LicenseId { get; set; }
public IList<SelectableDeviceViewModel> Devices { get; set; }
}
然后使用
for
循环代替foreach:@for (var i = 0; i < Model.Devices.Count; i++)
{
@Html.HiddenFor(x => x.Devices[i].DeviceInstanceId)
<tr>
<td>@Html.CheckBoxFor(x => x.Devices[i].IsSelected)</td>
<td>@Html.DisplayFor(x => x.Devices[i].Name</td>
</tr>
}
关于asp.net-mvc-3 - MVC3-具有复杂类型列表的Viewmodel,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11677831/