代码之家  ›  专栏  ›  技术社区  ›  Zachary Scott

复选框列出多个选择:如何建模绑定并获取所有选择?

  •  3
  • Zachary Scott  · 技术社区  · 14 年前

    此代码:

    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-method参数如下:

    public ActionResult Edit(Header header)
    
    3 回复  |  直到 13 年前
        1
  •  1
  •   Omu    14 年前

    当有多个同名项时,它们的值将用Coma分隔。

        2
  •  4
  •   Rob    14 年前

    我假设html.checkboxlist是您的扩展名,这是您生成的标记。

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

    1. 模型绑定器将查找名为header的对象,该对象的字符串属性h_dist_cd将绑定到。您的操作方法看起来像header是根视图模型,而不是模型的子对象。
    2. 我不知道你是如何处理复选框被清除的情况的。通常的技巧是渲染一个同名的隐藏字段。

    也是一个NIT,但您希望使用“label for=…”,以便他们可以单击文本以选中/取消选中和进行辅助功能。

    我发现使用扩展来解决这个问题很容易出错。您可能需要考虑使用子视图模型。它更适合于MVC2模板系统的编辑器。

    下面是我们系统的一个例子…

    在视图模型中,嵌入一个可重用的子模型…

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

    您可以用标准的selectListItem列表初始化它…

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

    多选择模型子模型。注意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/multisectmodel.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. 分离模型和视图(编辑器模板)。例如,我们有一个水平和垂直的复选框布局。您还可以将“多重选择”呈现为两个列表框,其中包含前后按钮、多重选择列表框等。

        3
  •  2
  •   Amir978    13 年前

    我认为您需要的是如何从用户选择的复选框列表中收集所选值,下面是我的解决方案:

    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-如您所见,我已将所有选定的值添加到数组中,并已通过Ajax 4将其传递给“Home”控制器的“Save”操作-在控制器中,您可以通过添加数组作为参数来接收这些值:

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

    我搜索了太多,但显然这是唯一的解决办法。如果你能找到更好的解决办法,请告诉我。