CheckBoxList множественный выбор: как смоделировать привязку и получить все выборы?

Этот код:

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

Производит эту наценку:

<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>

Вы можете проверить несколько вариантов. Возвращаемый строковый параметр Header.h_dist_cd содержит только первое выбранное значение. Что мне нужно сделать, чтобы получить другие проверенные значения?

Параметр метода post выглядит следующим образом:

public ActionResult Edit(Header header)

3 ответа

Решение

Если у вас есть несколько предметов с одинаковым именем, вы получите их значения через запятую

Я предполагаю, что Html.CheckBoxList - это ваше расширение, и это сгенерированная вами разметка.

На основании того, что вы показываете, нужно проверить две вещи:

  1. Связыватель модели будет искать объект с именем Header со строковым свойством h_dist_cd для привязки. Ваш метод действия выглядит так, как будто Header является моделью корневого представления, а не дочерним объектом вашей модели.
  2. Я не знаю, как вы справляетесь со случаем, когда флажки сняты. Обычный трюк - визуализация скрытого поля с тем же именем.

Тоже самое, но вы хотите использовать 'label for="..."', чтобы они могли щелкнуть текст, чтобы отметить / снять галочку и получить доступ.

Я обнаружил, что использование расширений для этой проблемы подвержено ошибкам. Возможно, вы захотите рассмотреть модель дочернего представления вместо этого. Это лучше вписывается в систему шаблонов EditorFor MVC2.

Вот пример из нашей системы...

В модель представления вставьте дочернюю модель многоразового использования...

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

Вы можете инициализировать его стандартным списком SelectListItem...

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

MultiSelectModel дочерняя модель. Обратите внимание на переопределение сеттера в 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; 
}

Теперь вы можете разместить свой шаблон редактора в 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) %>

Два преимущества этого подхода:

  1. Вам не нужно обрабатывать список элементов отдельно от значения выбора. Вы можете поместить атрибуты в одно свойство (например, AtLeastOneRequired - это пользовательский атрибут в нашей системе)

  2. Вы разделяете модель и вид (шаблон редактора). Например, у нас есть горизонтальная и вертикальная компоновка флажков. Вы также можете отобразить "множественный выбор" в виде двух списков с кнопками "назад" и "вперед", списком с множественным выбором и т. Д.

Я думаю, что вам нужно, как собрать выбранные значения из CheckBoxList, который выбрал пользователь, и вот мое решение для этого:

1- Загрузите Jquery.json.js и добавьте его в свой справочный документ:

2- Я добавил ".cssMyClass" ко всем элементам чекбоксов, поэтому я получаю значения по их классу css:

 <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. Как вы можете видеть, я добавил все выбранные значения в массив и передал его в действие "Сохранить" контроллера "Home" с помощью ajax 4- в контроллере вы можете получить значения, добавив массив в качестве аргумента:

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

Я искал слишком много, но, видимо, это единственное решение. Пожалуйста, дайте мне знать, если вы найдете лучшее решение для этого.

Другие вопросы по тегам