Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 3 MVC3-具有复杂类型列表的Viewmodel_Asp.net Mvc 3_Viewmodel_Model Binding_Checkboxfor - Fatal编程技术网

Asp.net mvc 3 MVC3-具有复杂类型列表的Viewmodel

Asp.net mvc 3 MVC3-具有复杂类型列表的Viewmodel,asp.net-mvc-3,viewmodel,model-binding,checkboxfor,Asp.net Mvc 3,Viewmodel,Model Binding,Checkboxfor,如果之前有人问过,请道歉;有一百万种表达方式,因此寻找答案被证明是困难的 我有一个具有以下属性的viewmodel: public class AssignSoftwareLicenseViewModel { public int LicenseId { get; set; } public ICollection<SelectableDeviceViewModel> Devices { get; set; } } 在我看来,我试图在输入表单中显示设备属性的可编辑复

如果之前有人问过,请道歉;有一百万种表达方式,因此寻找答案被证明是困难的

我有一个具有以下属性的viewmodel:

public class AssignSoftwareLicenseViewModel
{
    public int LicenseId { get; set; }
    public ICollection<SelectableDeviceViewModel> Devices { 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" />
}
@使用(Html.BeginForm())
{
@Html.HiddenFor(x=>Model.LicenseId)
名称
@foreach(Model.Devices中的SelectableDeviceViewModel设备)
{
@Html.HiddenFor(x=>device.DeviceInstanceId)
@CheckBoxFor(x=>device.IsSelected)
@设备名称
}
}
问题是,当模型发回控制器时,设备为空

我的假设是,这是因为即使我正在编辑其内容,Devices属性也从未明确包含在表单中。我尝试将其包含在HiddenFor中,但这只会导致模型的列表为空而不是空

知道我做错了什么吗

我的假设是这种情况正在发生,因为即使我 编辑其内容时,不会显式显示Devices属性 包括在表格中

不,你的假设是错误的。无法正确绑定的原因是您的输入字段没有正确的名称。例如,它们被称为
name=“IsSelected”
,而不是
name=“Devices[0]。IsSelected”
。查看绑定到集合时需要使用的正确导线格式:

但为什么会发生这种情况

这是因为在视图中使用了
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>
然后使用
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>
}
(变量i=0;ix.Devices[i].DeviceInstanceId) @Html.CheckBoxFor(x=>x.Devices[i].IsSelected) @DisplayFor(x=>x.Devices[i].Name }
editorfortemplates工作并保持代码干净。您不需要循环,模型会正确地发回


但是,是否有人在复杂viewmodels(嵌套的模板编辑器)的验证方面遇到问题?我正在使用Kendo Validator,遇到了各种各样的jquery错误。

你能给我们看一下你填充数据模型的控制器代码吗?+1是关于这个领域最优雅的描述问题。相信我,我们已经花了两个小时到处寻找这个问题!回答得很好,但你为什么不推荐使用索引收集视图模型中的循环?@JamieIde,因为我更喜欢使用编辑器模板。当框架已经考虑到这一点时,为什么要在视图中编写循环?@DarinDimitrov我明白你的观点,我想知道这是个人偏好还是另一个原因。有时我觉得有包含部分html的模板很奇怪(例如,在您的示例中表示一个表行)或jQuery在页面中引用的元素等。其效果是,模板只能在一个页面上使用,所以为什么要将其打破?@JamieIde,我想这确实是个人选择的问题。+1.在经过两个小时的查看和尝试后,在互联网上发布的唯一一篇文章。
public class AssignSoftwareLicenseViewModel
{
    public int LicenseId { get; set; }
    public IList<SelectableDeviceViewModel> Devices { get; set; }
}
@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>
}