ASP.Net MVC 3 Retrieve Checkbox List Values

2019-01-15 02:51发布

问题:

I am developing an ASP.Net MVC 3 Web application and I am having some difficulties with getting the values from a checkboxlist. I have already read most of the questions on Stackoverflow around this area, however, I am still having some issues.

I have a ViewModel

public class ViewModelCheckBox
{
    public string Id { get; set; }
    public string Name { get; set; }
    public bool Checked { get; set; }
}

Another ViewModel which use the viewmodel above

public class ViewModelAssignSubSpeciality
{
    public ListItem Item { get; set; }
    public IList<ViewModelCheckBox> SpecialityList { get; set; }
}

Then in my controller

public ActionResult AssignSubSpeciality(int id)
{
        //Get a list of all sub-specialities
        var SpecialityList = _listService.GetListItemsByID(3).ToList();

        //Get a list of sub-specialities for the the passed in id, this is either the id of a speciality or grade
        IList<RelationshipSpecialitySub> assignedSpecialities = _listService.GetAssignedSubSpecialities(id).ToList();

        var checkBoxList = new List<ViewModelCheckBox>();

        foreach (ListItem item in SpecialityList)
        {
            ViewModelCheckBox chkBox = new ViewModelCheckBox { Id = item.listItemID.ToString(), Name = item.description };

            //If sub-speciality exists in assignedSpecialities list, then make checkbox checked
            foreach (var specilaity in assignedSpecialities)
            {
                if (specilaity.subID == item.listItemID)
                {
                    chkBox.Checked = true;
                }
                else
                {
                    chkBox.Checked = false;
                }
            }

            checkBoxList.Add(chkBox);
        }

        ViewModelAssignSubSpeciality viewModel = new ViewModelAssignSubSpeciality();
        viewModel.ListItem = _listService.GetListItemByID(id);
        viewModel.SpecialityList = checkBoxList;

        return View(viewModel);
    }

The code in the controller above is getting a list of all the possible checkbox list items, then getting a list of all the previously selected checkbox list items for which it sets the checked option to true.

My View then looks like this, looping over the SpecialityList and creating a checkbox for each item, and also setting its selected value to true if needs be.

<fieldset>
<legend>Specialities</legend>

@foreach (var item in Model.SpecialityList)
{
<input type="checkbox" id="@item.Id" name="@item.Name" value="@item.Id" @(item.Checked ? "checked" : "") />
<label for="@item.Id">@item.Name</label><br />
}

<input type="submit" value="Save Changes" class="sepH_b" />                                         

My HttpPost method in my controller then looks like this

    public ActionResult AssignSubSpeciality(ViewModelAssignSubSpeciality model)
    {
        //delete all sub-specialities in tbl relationshipSpecialitySub for List
        foreach (ViewModelCheckBox item in model.SpecialityList)
        {
                //_listService.DeleteSubSpecialityFromSpeciality(item.Id);
        }

        return RedirectToAction("ListItems", new { id = model.ListItem.listID });
    }

However, when I try to get the selected checkboxes in

model.SpecialityList

It us always null. I am not sure why it doesnt contain a list of ViewModelCheckBox.

Can anyone please help me with this?

Thank you.

回答1:

I have an Enumerable of these in my view model

public class CheckBoxItem
{
   public string Code { get; set; }
   public bool IsChecked { get; set; }
   public string Label {get;set;}
}

I then use an editor template to display them on the page.

<p class="checkbox" style="display:inline">
<span style="margin-left:5px;">
    @Html.HiddenFor(x => x.Code)           
    @Html.CheckBoxFor(x => x.IsChecked)
</span>
@Html.LabelFor(x => x.IsChecked, Model.Label)
</p>

In the view I use the following to display them on the page.

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

When the form is posted back the model is correctly bound.

Hope this helps.



回答2:

It's because you gave the checkbox the name @item.Name. The model binder will check if it can map it to a particular property in the model, but it can't find it because it is looking for the value of @item.Name and not for the SpecialtyList property.

Phil Haack has a nice article about model binding to a list. I suggest you check that one out.

Also, I don't think you can model bind to a custom object, because the values of the checkboxes that are coming in is are just strings. You should make another property on your model that is of type IEnumerable to which the values of the checkboxes are model binded. It would look like this:

public IList<ViewModelCheckBox> SpecialityList { get; set; }
public IEnumerable<string> SpecialityListValues { get; set; }

This way you can use the SpecialityList to fill the values in the view, and the SpecialityListValues to retrieve the values. Note that the name of the checkboxes has to correspond with SpecialityListValues.



回答3:

@RubbleFord has provided a great answer. It can fall down if you have multiple lists being created on the same page though, as the labels For property will reference a label further up the page.

To resolve this I've changed the Editor Template to this:

<p class="checkbox" style="display:inline">
    <label>
        @Html.HiddenFor(x => x.Code)
        @Html.CheckBoxFor(x => x.IsChecked)
        @Model.Label
    </label>
</p>

Everything else is the same, but this wraps the checkbox with the label, so the For can be removed.