MVC3 - 视图模型复杂类型列表 [英] MVC3 - Viewmodel with list of complex types

查看:226
本文介绍了MVC3 - 视图模型复杂类型列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果这个道歉已经问;有一百万的方式句话就那么寻找答案已被证明很难。

我有一个视图模型具有以下属性:

 公共类AssignSoftwareLicenseViewModel
{
    公众诠释LicenseId {搞定;组; }
    公众的ICollection< SelectableDeviceViewModel>设备{搞定;组; }
}

SelectableDeviceViewModel的简化版本是这样的:

 公共类SelectableDeviceViewModel
{
    公众诠释DeviceInstanceId {搞定;组; }
    公共BOOL IsSelected {搞定;组; }
    公共字符串名称{;组; }
}

在我看来,我试图以显示设备的属性可编辑复选框列表,输入表单中。
目前,我的看法是这样的:

  @using(Html.BeginForm())
{
    @ Html.HiddenFor(X => Model.LicenseId)
    <表>
        &所述; TR>
            <第i个姓名和LT; /第i
            百分位>< /第i
        < / TR>
        @foreach(在Model.Devices SelectableDeviceViewModel设备)
        {
            @ Html.HiddenFor(X => device.DeviceInstanceId)
            &所述; TR>
                < TD> @ Html.CheckBoxFor(X => device.IsSelected)LT; / TD>
                < TD> @ device.Name< / TD>
            < / TR>
        }
    < /表>    <输入类型=提交值=分配/>
}

问题是,当模型被调回控制器,设备为null。

我的假设是,这种情况正在发生,因为即使我编辑的内容,该设备的属性从未明确地包含在表单中。我试着包括它HiddenFor,但只是导致有一个空列表而不是空的模式。

任何想法,我在做什么错在这里?


解决方案

  

我的假设是,这种情况正在发生,因为即使我
  编辑其内容的设备属性是从未明确
  包括在形式


没有,你的假设是错误的。这并没有得到正确绑定的原因是因为你的输入字段没有正确的名称。例如,他们被称为 NAME =IsSelected而不是 NAME =设备[0] .IsSelected。看看正确的线格式,需要使用绑定到集合:<一href=\"http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx\">http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx


  

但是,为什么出现这种情况?


这是因为您在视图中使用的的foreach 循环。你用 X =&GT; device.IsSelected 为lambda前pression的复选框,但这并不考虑设备的属性在所有(你可以通过查看生成的源$ C ​​$ C看到你网页)。


  

那么,应该怎么办?


我个人使用编辑模板,因为他们尊重复杂属性的导航上下文,并产生正确的输入名称推荐你。因此,获得在你看来摆脱了整个的foreach 循环,用code一行替换为:

  @ Html.EditorFor(X =&GT; x.Devices)

和现在定义将自动ASP.NET MVC的设备集合中的每个元素呈现一个自定义编辑器模板。警告:此模板的位置和名称都为这个非常重要的工作原理是约定:〜/查看/共享/ EditorTemplates / SelectableDeviceViewModel.cshtml

  @model SelectableDeviceViewModel
@ Html.HiddenFor(X =&GT; x.DeviceInstanceId)
&所述; TR&GT;
    &LT; TD&GT; @ Html.CheckBoxFor(X =&GT; x.IsSelected)LT; / TD&GT;
    &LT; TD&GT; @ Html.DisplayFor(X =&GT; x.Name)LT; / TD&GT;
&LT; / TR&GT;


另一种方法(我不建议)是改变你目前的的ICollection 在您的视图模式向的索引的集合(如一个的IList&LT; T&GT; 或数组 T []

 公共类AssignSoftwareLicenseViewModel
{
    公众诠释LicenseId {搞定;组; }
    公众的IList&LT; SelectableDeviceViewModel&GT;设备{搞定;组; }
}

然后,而不是在foreach使用循环:

  @for(VAR I = 0; I&LT; Model.Devices.Count;我++)
{
    @ Html.HiddenFor(X =&GT; x.Devices [I] .DeviceInstanceId)
    &所述; TR&GT;
        &LT; TD&GT; @ Html.CheckBoxFor(X =&GT; x.Devices [I] .IsSelected)LT; / TD&GT;
        &LT; TD&GT; @ Html.DisplayFor(X =&GT; x.Devices [I] .Name点&LT; / TD&GT;
    &LT; / TR&GT;
}

Apologies if this has been asked before; there are a million ways to phrase it so searching for an answer has proved difficult.

I have a viewmodel with the following properties:

public class AssignSoftwareLicenseViewModel
{
    public int LicenseId { get; set; }
    public ICollection<SelectableDeviceViewModel> Devices { get; set; }
}

A simplified version of SelectableDeviceViewModel would be this:

public class SelectableDeviceViewModel
{
    public int DeviceInstanceId { get; set; }
    public bool IsSelected { get; set; }
    public string Name { get; set; }
}

In my View, I am attempting to display a list of editable checkboxes for the Devices property, inside an input form. Currently, my View looks like this:

@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" />
}

The problem is, when the model gets posted back to the controller, Devices is null.

My assumption is that this is happening because even though I'm editing its contents, the Devices property is never explicitly included in the form. I tried including it with HiddenFor, but that just resulted in the model having an empty list instead of null.

Any idea what I'm doing wrong here?

解决方案

My assumption is that this is happening because even though I'm editing its contents, the Devices property is never explicitly included in the form.

No, your assumption is wrong. The reason this doesn't get bound properly is because your input fields doesn't have correct names. For example they are called name="IsSelected" instead of name="Devices[0].IsSelected". Take a look at the correct wire format that needs to be used to bind to collections: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

But why this happens?

It happens because of the foreach loop that you used in your view. You used x => device.IsSelected as lambda expression for the checkbox but this doesn't take into account the Devices property at all (as you can see by looking at the generated source code of your web page).

So what should I do?

Personally I would recommend you using editor templates as they respect the navigational context of complex properties and generate correct input names. So get rid of the entire foreach loop in your view and replace it with a single line of code:

@Html.EditorFor(x => x.Devices)

and now define a custom editor template that will automatically be rendered by ASP.NET MVC for each element of the Devices collection. Warning: the location and name of this template are very important as this works by convention: ~/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>


Another approach (which I don't recommend) is to change your current ICollection in your view model to an indexed collection (such as an IList<T> or an array T[]):

public class AssignSoftwareLicenseViewModel
{
    public int LicenseId { get; set; }
    public IList<SelectableDeviceViewModel> Devices { get; set; }
}

and then instead of the foreach use a for loop:

@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>
}

这篇关于MVC3 - 视图模型复杂类型列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆