Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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 ?

like image 338
Mech0z Avatar asked Dec 02 '11 13:12

Mech0z


1 Answers

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>
like image 118
Darin Dimitrov Avatar answered Oct 06 '22 17:10

Darin Dimitrov