ASP.NET MVC 4 and MVCContrib Grid: Render Checkbox for each TR and Post values in complex type
Asked Answered
O

1

0

MVCContrib Grid:

@model ViewModel
@using (Html.BeginForm("SendData", "Home", FormMethod.Post))
{
    @Html.Grid(Model.List).Columns(c =>
    {
        c.For(x => x.Id);
        c.For(x => x.Name);
        c.For(x =>Html.Partial("Partial/CheckBoxTemplate", new CheckBoxViewModel { Id = x.Id })).Named("Options");
    })

    @Html.SubmitButton()
}

Controller Post Action:

public ActionResult SendData(List<CheckBoxViewModel> list)
{
    return View();
}

ViewModels:

public class CheckBoxViewModel
{
    public int Id { get; set; }
    public bool CheckBox { get; set; }
}

public class ViewModel
{
    public IPagination<Data> List { get; set; }
}

public class Data
{
    public int Id { get; set; }
    public string Name { get; set; } 
}

Partial View:

@model MvcApplication1.Models.CheckBoxViewModel

@Html.HiddenFor(x => x.Id)
@Html.CheckBoxFor(x => x.CheckBox)

All checkboxed are by default not checked.

How can I retrieve all checked checkbox values in my SendData action?

Oswaldooswalt answered 28/10, 2012 at 16:54 Comment(2)
What's inside Partial/CheckBoxTemplate.cshtml? Also you seem to be binding to some Name property (c.For(x => x.Name);) but I can't see such property defined in your CheckBoxViewModel. Could you please show your real code?Hexane
But you are passing only the Id to your partial and you never set the boolean CheckBox property. Why aren't you using a view model? Why does your ViewModel uses an IPagination<Data> property instead of IPagination<CheckBoxViewModel> which would have made much more sense since you are attempting to generate checkboxes in your view?Hexane
H
1

I would recommend you to use a real view model that will reflect the requirements of your view (displaying a grid containing for each row a checkbox, and displaying the id and name of the item and retrieving those values in a list in your postback action):

public class CheckBoxViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool CheckBox { get; set; }
}

public class ViewModel
{
    public IPagination<CheckBoxViewModel> List { get; set; }
}

and then have your view strongly typed to this view model:

@model ViewModel

@using (Html.BeginForm("SendData", "Home", FormMethod.Post))
{
    @Html.Grid(Model.List).Columns(c =>
    {
        c.For(x => x.Id);
        c.For(x => x.Name);
        c.For(x => Html.Partial("Partial/CheckBoxTemplate", x)).Named("Options");
    })

    <button type="submit">OK</button>
}

finally your partial could look like this:

@model CheckBoxViewModel

@{
    var index = Guid.NewGuid().ToString();
}

@Html.Hidden("list.Index", index)
@Html.Hidden("list[" + index + "].Id", Model.Id)
@Html.Hidden("list[" + index + "].Name", Model.Name)
@Html.CheckBox("list[" + index + "].CheckBox", Model.CheckBox)

Now when the SendData action is invoked it will be passed the list of your view model.

Alternatively you could use the Html.BeginCollectionItem helper presented in the following article which would allow you to use the strongly typed versions of the helpers:

@model CheckBoxViewModel
@using(Html.BeginCollectionItem("list")) 
{
    @Html.HiddenFor(x => x.Id)
    @Html.HiddenFor(x => x.Name)
    @Html.CheckBoxFor(x => x.CheckBox)
}

Recommended further reading: Model Binding To A List.

Hexane answered 28/10, 2012 at 17:38 Comment(2)
There is one thing that is surprising me: Why is CheckBoxFor creating an additional input hidden field?Oswaldooswalt
Because in HTML checkboxes do not send the value if the checkbox is not checked. So the ChekBox helper adds an additional hidden field with hardcoded false value. This way if the checkbox is not selected false will be bound to the boolean field of the view model and if the checkbox is checked, 2 values with the same name will be sent: true and false, and the first value will be bound.Hexane

© 2022 - 2024 — McMap. All rights reserved.