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 - это ваше расширение, и это сгенерированная вами разметка.
На основании того, что вы показываете, нужно проверить две вещи:
- Связыватель модели будет искать объект с именем Header со строковым свойством h_dist_cd для привязки. Ваш метод действия выглядит так, как будто Header является моделью корневого представления, а не дочерним объектом вашей модели.
- Я не знаю, как вы справляетесь со случаем, когда флажки сняты. Обычный трюк - визуализация скрытого поля с тем же именем.
Тоже самое, но вы хотите использовать '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) %>
Два преимущества этого подхода:
Вам не нужно обрабатывать список элементов отдельно от значения выбора. Вы можете поместить атрибуты в одно свойство (например, AtLeastOneRequired - это пользовательский атрибут в нашей системе)
Вы разделяете модель и вид (шаблон редактора). Например, у нас есть горизонтальная и вертикальная компоновка флажков. Вы также можете отобразить "множественный выбор" в виде двух списков с кнопками "назад" и "вперед", списком с множественным выбором и т. Д.
Я думаю, что вам нужно, как собрать выбранные значения из 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)
{
Я искал слишком много, но, видимо, это единственное решение. Пожалуйста, дайте мне знать, если вы найдете лучшее решение для этого.