CheckBoxList multiple selections: how to model bind back and get all selections?

橙三吉。 提交于 2019-12-22 10:53:21

问题


This code:

Html.CheckBoxList(ViewData.TemplateInfo.HtmlFieldPrefix, myList)

Produces this mark-up:

<ul><li><input name="Header.h_dist_cd" type="checkbox" value="BD" />
        <span>BD - Dist BD Name</span></li>
    <li><input name="Header.h_dist_cd" type="checkbox" value="SS" />
        <span>SS - Dist SS Name</span></li>
    <li><input name="Header.h_dist_cd" type="checkbox" value="DS" />
        <span>DS - Dist DS Name</span></li>
    <li><input name="Header.h_dist_cd" type="checkbox" value="SW" />
        <span>SW - Dist SW Name </span></li>
</ul>

You can check multiple selections. The return string parameter Header.h_dist_cd only contains the first value selected. What do I need to do to get the other checked values?

The post method parameter looks like this:

public ActionResult Edit(Header header)

回答1:


when you have multiple items with the same name you will get their values separated with coma




回答2:


I'm assuming that Html.CheckBoxList is your extension and that's markup that you generated.

Based on what you're showing, two things to check:

  1. The model binder is going to look for an object named Header with string property h_dist_cd to bind to. Your action method looks like Header is the root view model and not a child object of your model.
  2. I don't know how you are handling the case where the checkboxes are cleared. The normal trick is to render a hidden field with the same name.

Also a nit, but you want to use 'label for="..."' so they can click the text to check/uncheck and for accessibility.

I've found that using extensions for this problem is error prone. You might want to consider a child view model instead. It fits in better with the EditorFor template system of MVC2.

Here's an example from our system...

In the view model, embed a reusable child model...

[AtLeastOneRequired(ErrorMessage = "(required)")]
public MultiSelectModel Cofamilies { get; set; }

You can initialize it with a standard list of SelectListItem...

MyViewModel(...)
{
  List<SelectListItem> initialSelections = ...from controller or domain layer...;
  Cofamilies = new MultiSelectModel(initialSelections);
  ...

The MultiSelectModel child model. Note the setter override on Value...

public class MultiSelectModel : ICountable
{
  public MultiSelectModel(IEnumerable<SelectListItem> items)
  {
    Items = new List<SelectListItem>(items);
    _value = new List<string>(Items.Count);
  } 

  public int Count { get { return Items.Count(x => x.Selected); } } 
  public List<SelectListItem> Items { get; private set; }

  private void _Select()
  {
    for (int i = 0; i < Items.Count; i++)
      Items[i].Selected = Value[i] != "false";
  }

  public List<SelectListItem> SelectedItems
  {
    get { return Items.Where(x => x.Selected).ToList(); }
  } 

  private void _SetSelectedValues(IEnumerable<string> values)
  {
    foreach (var item in Items)
    {
      var tmp = item;
      item.Selected = values.Any(x => x == tmp.Value);
    }
  } 

  public List<string> SelectedValues
  {
    get { return SelectedItems.Select(x => x.Value).ToList(); }
    set { _SetSelectedValues(value); }
  } 

  public List<string> Value
  {
    get { return _value; }
    set { _value = value; _Select(); }
  }
  private List<string> _value; 
}

Now you can place your editor template in Views/Shared/MultiSelectModel.ascx...

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<WebUI.Cofamilies.Models.Shared.MultiSelectModel>" %>

<div class="set">

<%=Html.LabelFor(model => model)%>

<ul>
  <% for (int i = 0; i < Model.Items.Count; i++)
  {
    var item = Model.Items[i];
    string name = ViewData.ModelMetadata.PropertyName + ".Value[" + i + "]";
    string id = ViewData.ModelMetadata.PropertyName + "_Value[" + i + "]";
    string selected = item.Selected ? "checked=\"checked\"" : "";
  %>
  <li>
    <input type="checkbox" name="<%= name %>" id="<%= id %>" <%= selected %> value="true" />
    <label for="<%= id %>"><%= item.Text %></label>
    <input type="hidden" name="<%= name %>" value="false" />
  </li>
  <% } %>
</ul>
<%= Html.ValidationMessageFor(model => model) %>

Two advantages to this approach:

  1. You don't have to treat the list of items separate from the selection value. You can put attributes on the single property (e.g., AtLeastOneRequired is a custom attribute in our system)

  2. you separate model and view (editor template). We have a horizontal and a vertical layout of checkboxes for example. You could also render "multiple selection" as two listboxes with back and forth buttons, multi-select list box, etc.




回答3:


I think what you need is how gather selected values from CheckBoxList that user selected and here is my solution for that:

1- Download Jquery.json.js and add it to your view as reference:

2- I've added a ".cssMyClass" to all checkboxlist items so I grab the values by their css class:

 <script type="text/javascript" >
       $(document).ready(function () {
           $("#btnSubmit").click(sendValues);
         });

     function populateValues()
     {
         var data = new Array();
         $('.myCssClas').each(function () {
             if ($(this).attr('checked')) {
                 var x = $(this).attr("value");
                 data.push(x);
             }
         }); 

         return data;
     }

     function sendValues() {
         var data = populateValues();
               $.ajax({
                   type: 'POST',
                   url: '@Url.Content("~/Home/Save")',
                   data: $.json.encode(data),
                   dataType: 'json',
                   contentType: 'application/json; charset=utf-8',
                   success: function () { alert("1"); }
               });

       } 



 </script>

3- As you can see I've added all selected values to an Array and I've passed it to "Save" action of "Home" controller by ajax 4- in Controller you can receive the values by adding an array as argument:

 [HttpPost]
        public ActionResult Save(int[] val)
        {

I've searched too much but apparently this is the only solution. Please let me know if you find a better solution for it.



来源:https://stackoverflow.com/questions/3369533/checkboxlist-multiple-selections-how-to-model-bind-back-and-get-all-selections

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!