-1

I have the following view model code:

public class TestCheckboxlistParentModel
{
    public TestCheckboxlistParentModel()
    {
        CBL = new TestCheckboxlistModel();
    }
    public TestCheckboxlistModel CBL { get; set; }
}

public class TestCheckboxlistModel
{
    public string TextField { get; set; }
    public IList<string> SelectedFruits { get; set; }
    public IList<SelectListItem> AvailableFruits { get; set; }

    public TestCheckboxlistModel()
    {
        SelectedFruits = new List<string>();
        AvailableFruits = new List<SelectListItem>();
    }
}

controller:

    public ActionResult TestCheckboxlist()
    {
        var model = new TestCheckboxlistParentModel
        {
            CBL = new TestCheckboxlistModel()
            {
                AvailableFruits = GetFruits()
            }
        };
        return View(model);
    }

    [HttpPost]
    public ActionResult TestCheckboxlist(TestCheckboxlistParentModel model)
    {
        if (ModelState.IsValid)
        {
            // Save data to database, and redirect to Success page.

            return RedirectToAction("Success");
        }
        //model.AvailableFruits = GetFruits();
        return View(model);
    }

    public ActionResult Success()
    {
        return View();
    }

    private IList<SelectListItem> GetFruits()
    {
        return new List<SelectListItem>
    {
        new SelectListItem {Text = "Apple", Value = "1"},
        new SelectListItem {Text = "Pear", Value = "2"},
        new SelectListItem {Text = "Banana", Value = "3"},
        new SelectListItem {Text = "Orange", Value = "4"},
        };
    }

partial view:

@model Web.ViewModels.TestCheckboxlistModel

<div class="form-group">
    @Html.LabelFor(model => model.TextField)
    <div class="col-md-10">
        @Html.EditorFor(model => model.TextField)
    </div>
</div>

    @foreach (var item in Model.AvailableFruits)
    {
<div class="checkbox">
    <label>
        <input type="checkbox"
               name="@Html.IdFor(p=>p.SelectedFruits)"
               value="@item.Value" /> @item.Text
        </label>
    </div>
    }

view:

@model Web.ViewModels.TestCheckboxlistParentModel

@{
    ViewBag.Title = "TestCheckboxlist";
    Layout = "~/Views/Shared/_LayoutApplicationDriver.cshtml";
}

@using (Html.BeginForm())
{

    @Html.Partial("TestPartialCheckboxlist", Model.CBL, new ViewDataDictionary { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "CBL" } })
    <div class="form-group text-center">
        <input type="submit" class="btn btn-primary" value="Submit" />
    </div>
}

Problem is SelectedFruits always does not have any elements in post method. The same code work correctly, if I don't use nested Partial view. Property TextField works fine with Partial

PS. It's not a dublicate of How to make Check Box List in ASP.Net MVC question. That question is a base of my answer. In my case, I need to have checkboxlist in partial view, where it does not work!

Oleg Sh
  • 8,496
  • 17
  • 89
  • 159
  • 1
    Possible duplicate of [How to make Check Box List in ASP.Net MVC](https://stackoverflow.com/questions/37778489/how-to-make-check-box-list-in-asp-net-mvc) – David Lee Oct 02 '17 at 20:49
  • Looks like you have gotten help from this question https://stackoverflow.com/a/37779070/6535663. In your partial view for the input/checkbox change the name to `SelectedFruits`. ` @item.Text ` – David Lee Oct 02 '17 at 20:50
  • Put the partial in the Edit folder of your views and call the editor-for template on the main view. My guess is that since you are only rendering a partial and not an edit template, the view isn't adding the parent information to the ID like it should. – Blast_dan Oct 02 '17 at 20:51
  • This is an odd way to create a checkbox list. Suggest you refer the code in [this answer](https://stackoverflow.com/questions/29542107/pass-list-of-checkboxes-into-view-and-pull-out-ienumerable/29554416#29554416) –  Oct 02 '17 at 20:51
  • @DavidLee, it's not a dublicate – Oleg Sh Oct 02 '17 at 21:04
  • @DavidLee, I know about naming inside partial views. I use Html.IdFor(p=>p.SelectedFruits). But it works for textbox, not for checkboxlist... – Oleg Sh Oct 02 '17 at 21:05

1 Answers1

2

You use of name="@Html.IdFor(p => p.SelectedFruits)" generates name="CBL_SelectedFruits", but in order to bind to your model, you would need name="CBL.SelectedFruits" (note the . dot, not _ underscore) which you could generate using

name="@Html.NameFor(p => p.SelectedFruits)"

However there are other issues with your code. Your not strongly binding to your model, you get no validation, your generating a IList<SelectListItem> for property AvailableFruits when you don't need it (it could be just IList<string> AvailableFruits, and most importantly, if you return the view, all the checkboxes the user checked are lost (all checkboxes will be unchecked).

Change your view models so that you can strongly bind to your properties

public class FruitVM
{
    public string Name { get; set; }
    public bool IsSelected { get; set; }
}
public class ParentVM
{
    public string TextField { get; set; }
    public List<FruitVM> Fruits { get; set; }
}

and in the GET method

ParentVM model = new ParentVM
{
    Fruits = new List<FruitVM>{ 
        new FruitVM{ Name = "Apple" },
        new FruitVM{ Name = "Pear" }, 
        ....       
    }
};
return View(model);

and create an EditorTemplate for FruitVM - in /Views/Shared/EditorTemplates/FruitVM.cshtml

@model FruitVM
@Html.CheckBoxFor(m => m.IsSelected)
@Html.LabelFor(m => m.IsSelected, Model.Name)

and in the view

@Html.ParentVM
....
@using (Html.BeginForm())
{
    @Html.LabelFor(m => m.TextField)
    @Html.EditorFor(m => m.TextField)

    @Html.EditorFor(m => m.Fruits)

    <input type="Submit" value="Save" />
}

The EditorFor() method will generate the correct html for each item in your collection.

Then in the POST method, you can get the selected items with

[HttpPost]
public ActionResult TestCheckboxlist(ParentVM model)
{
    ....
    List<string> selectedFruits = model.Fruits.Where(x => x.IsSelected);
  • Excellent! Thank you for good explaining! At last I have a good and flexible solution for checkbox list in ASP.NET MVC, without rough hard-coded things etc. – Oleg Sh Oct 03 '17 at 12:30