Create MVC3 CheckBoxFor from List<T> and getting the list back (With updated values) on Post

10,737

Start by fixing your view model and removing the custom constructor or the default model binder won't be able to instantiate it and you will have to write custom model binders and stuff:

public class BoolSetting
{
    public string DisplayName { get; set; }
    public bool Value { get; set; }
}

public class MyViewModel
{
    public List<BoolSetting> Settings { get; set; }
}

Then write a controller action that will populate your view model:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new MyViewModel
        {
            Settings = new[] 
            {
                new BoolSetting { DisplayName = "name 1", Value = true },
                new BoolSetting { DisplayName = "name 2", Value = false },
                new BoolSetting { DisplayName = "name 3", Value = true },
            }.ToList()
        };
        return View(model);
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return View(model);
    }
}

then a view (~/Views/Home/Index.cshtml) in which you simply use editor templates and don't write any foreach loops or weakly typed html helpers such as Html.CheckBox. By using editor templates you will ensure that all input fields will have correct names so that the default model binder is able to fetch their values into the view model during the postback:

@model MyViewModel
@using (Html.BeginForm())
{
    @Html.EditorFor(x => x.Settings)
    <button type="submit">OK</button>
}

and finally the corresponding editor template for the view model which will be rendered for each element of the collection (~/Views/Home/EditorTemplates/BoolSetting.cshtml):

@model BoolSetting
<div>
    @Html.CheckBoxFor(x => x.Value)
    @Html.LabelFor(x => x.Value, Model.DisplayName)
    @Html.HiddenFor(x => x.DisplayName)
</div>
Share:
10,737
Mech0z
Author by

Mech0z

Software Engineer Jan 2013

Updated on June 18, 2022

Comments

  • Mech0z
    Mech0z about 2 years

    I have a List in my ViewModel I parse to the View

    List<BoolSetting> 
    

    BoolSetting:

        public class BoolSetting
    {
        public BoolSetting(string displayName, bool value)
        {
            DisplayName = displayName;
            Value = value;
        }
        public string DisplayName { get; set; }
        public bool Value { get; set; }
    }
    

    I then want to print a checkbox for all the items in my list, so the list is in the ViewModel the view uses

    @foreach(var boolSettingList in Model.BoolSettingList)
            {
                <div>
                    @Html.CheckBox(boolSettingList.DisplayName, boolSettingList.Value)
                    @boolSettingList.DisplayName
                </div>
            }
    

    The problem is when I post this then my Model have not saved the updated settings (The bool values) in the List in my ViewModel and therefore the object is empty.

    I could do

    foreach (var VARIABLE in userSettingConfigViewModel.BoolSettingList)
            {
                VARIABLE.Value = (bool)Request.Form[VARIABLE.DisplayName];
    
            }
    

    But this viewmodel will have many lists and some of them will have the same names! So that will cause conflicts

    So is there a way to foreach print all my bools and then make MVC figure out to put the data back into the List object after? I cant get CheckBoxFor to work as it wants an expression and I cant figure out a way to itterate through my list that way

    Can I maybe fix it with Templates, by making a template for BoolSetting and maybe List ?

  • Mech0z
    Mech0z over 12 years
    Thanks, I was pretty close after I started using a Template for my BoolSetting, but didnt know I coudl just do @Html.EditorFor(x => x.Settings) but awesome ! >(