MVC3使用CheckBox和复杂的viewmodel

时间:2011-04-15 09:51:21

标签: asp.net-mvc checkbox controller viewmodel

合适的人。我需要你的大脑,因为我找不到合适的方法。

我有一个视图模型:

public class EditUserViewModel
{
    public User User;
    public IQueryable<ServiceLicense> ServiceLicenses;
}

用户并不重要,因为我知道如何处理它。

ServiceLicenses具有以下实现:

public class ServiceLicense
{
    public Guid ServiceId { get; set; }
    public string ServiceName { get; set; }
    public bool GotLic { get; set; }
}

获取已检查的用户列表很酷。它就像一个魅力。

<fieldset>
    <legend>Licenses</legend>
    @foreach (var service in Model.ServiceLicenses)
    {     
    <p>
        @Html.CheckBoxFor(x => service.GotLic)
        @service.ServiceName
    </p>
    } 
</fieldset>

我遇到的问题是将更新的ServiceLicenses对象与新的已检查服务一起返回到我的控制器中的HttpPost。为简单起见,我们可以这样说:

    [HttpPost]
    public ActionResult EditUser(Guid id, FormCollection collection)
    {

        var userModel = new EditUserViewModel(id);
        if (TryUpdateModel(userModel))
        {
            //This is fine and I know what to do with this
            var editUser = userModel.User;

            //This does not update
            var serviceLicenses = userModel.ServiceLicenses;

            return RedirectToAction("Details", new { id = editUser.ClientId });
        }
        else
        {
            return View(userModel);
        }
    }

我知道我正在以错误的方式使用CheckBox。我需要更改什么才能使用表单中选中的框来更新serviceLicenses?

1 个答案:

答案 0 :(得分:2)

我知道ServiceLicenses属性是一个集合,您希望MVC绑定器将其绑定到您的操作参数属性。为此,您应该在视图中附加带有输入的索引,例如

<input type="checkbox" name = "ServiceLicenses[0].GotLic" value="true"/>
<input type="checkbox" name = "ServiceLicenses[1].GotLic" value="true"/>
<input type="checkbox" name = "ServiceLicenses[2].GotLic" value="true"/>

前缀可能不是强制性的,但在绑定action方法参数的collection属性时非常方便。为此目的,我建议使用for循环而不是foreach并使用Html.CheckBox助手而不是Html.CheckBoxFor

<fieldset>
    <legend>Licenses</legend>
    @for (int i=0;i<Model.ServiceLicenses.Count;i++)
    {     
    <p>
        @Html.CheckBox("ServiceLicenses["+i+"].GotLic",ServiceLicenses[i].GotLic)
        @Html.CheckBox("ServiceLicenses["+i+"].ServiceName",ServiceLicenses[i].ServiceName)//you would want to bind name of service in case model is invalid you can pass on same model to view
        @service.ServiceName
    </p>
    } 
</fieldset>

不使用强类型助手只是个人偏好。如果你不想像这样索引你的输入,你也可以看看史蒂夫森德森这个伟大的post

编辑:我有blogged关于在asp.net mvc3上创建主详细信息表单,这也与列表绑定有关。