CheckBoxList多个选择:如何建模绑定并获取所有选择?

时间:2010-07-30 07:41:45

标签: templates asp.net-mvc-2 checkboxlist model-binding

此代码:

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 个答案:

答案 0 :(得分:4)

我假设Html.CheckBoxList是你的扩展名和你生成的标记。

根据您要展示的内容,需要检查两件事:

  1. 模型绑定器将查找名为Header的对象,其字符串属性为h_dist_cd以进行绑定。您的操作方法看起来像Header是根视图模型,而不是模型的子对象。
  2. 我不知道你是如何处理清除复选框的情况。通常的技巧是渲染一个具有相同名称的隐藏字段。
  3. 也是一个尼特,但你想使用'label for =“...”'这样他们就可以点击文本来检查/取消选中和访问。

    我发现使用此问题的扩展程序容易出错。您可能想要考虑子视图模型。它适用于MVC2的EditorFor模板系统。

    以下是我们系统的一个例子......

    在视图模型中,嵌入了可重用的子模型......

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

    您可以使用标准的SelectListItem列表初始化它......

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

    MultiSelectModel子模型。请注意Value ...

    上的setter覆盖
    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. 您将模型和视图(编辑器模板)分开。例如,我们有一个水平和垂直的复选框布局。您还可以使用来回按钮,多选列表框等将“多选”呈现为两个列表框。

答案 1 :(得分:2)

我认为你需要的是如何收集用户选择的CheckBoxList中的选定值,这是我的解决方案:

1-下载Jquery.json.js并将其作为参考添加到您的视图中:

2-我在所有checkboxlist项目中添加了“.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-正如您所看到的,我已将所有选定的值添加到数组中,并且我已通过ajax 4-将其传递给“Home”控制器的“Save”操作,您可以通过添加数组来接收值作为论点:

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

我搜索得太多,但显然这是唯一的解决方案。如果您找到更好的解决方案,请告诉我。

答案 2 :(得分:1)

当您有多个具有相同名称的项目时,您将使用逗号分隔其值