首页 文章

如何处理ASP.NET MVC表单中的复选框?

提问于
浏览
246

警告:这个问题已经超过9年了!

您最好的选择是搜索更新的问题,或搜索下面的答案,寻找您的MVC的特定版本,因为现在许多答案已经过时 .

如果您确实找到适合您的版本的答案,请确保答案包含您正在使用的MVC版本 .
(原始问题从下面开始)


这对我来说似乎有点奇怪,但就我所知,这就是你如何做到的 .

我有一组对象,我希望用户选择其中一个或多个 . 这对我说“形式有复选框” . 我的对象没有任何“选择”的概念(它们是通过反序列化wcf调用形成的基本POCO) . 所以,我做了以下事情:

public class SampleObject{
  public Guid Id {get;set;}
  public string Name {get;set;}
}

在视图中:

<%
    using (Html.BeginForm())
    {
%>
  <%foreach (var o in ViewData.Model) {%>
    <%=Html.CheckBox(o.Id)%>&nbsp;<%= o.Name %>
  <%}%>
  <input type="submit" value="Submit" />
<%}%>

并且,在控制器中,这是我可以看到用来检查用户检查的对象的唯一方法:

public ActionResult ThisLooksWeird(FormCollection result)
{
  var winnars = from x in result.AllKeys
          where result[x] != "false"
          select x;
  // yadda
}

它首先是怪异的,其次,对于用户检查的那些项,FormCollection将其值列为“真假”而不仅仅是真 .

显然,我错过了一些东西 . 我认为这是基于这样的想法构建的,即在html表单中作用的集合中的对象使用 UpdateModel() 或通过ModelBinder进行更新 .

但我没有为此设置对象;这是否意味着这是唯一的方法?还有另一种方法吗?

22 回答

  • 2

    这样的事怎么样?

    bool isChecked = false;
    if (Boolean.TryParse(Request.Form.GetValues(”chkHuman”)[0], out isChecked) == false)
        ModelState.AddModelError(”chkHuman”, “Nice try.”);
    
  • 54

    您还应该使用 <label for="checkbox1">Checkbox 1</label> ,因为人们可以点击标签文本以及复选框本身 . 它也更容易风格,至少在IE中,当你浏览页面的控件时它会突出显示 .

    <%= Html.CheckBox("cbNewColors", true) %><label for="cbNewColors">New colors</label>
    

    这不仅仅是'哦,我能做到'的事情 . 它是一项重要的用户体验增强 . 即使并非所有用户都知道他们可以点击许多标签 .

  • 49

    我很惊讶这些答案都没有使用内置的MVC功能 .

    我写了一篇关于这个here的博客文章,它实际上甚至将标签链接到复选框 . 我使用EditorTemplate文件夹以干净和模块化的方式完成此任务 .

    您将在EditorTemplate文件夹中最终得到一个新文件,如下所示:

    @model SampleObject
    
    @Html.CheckBoxFor(m => m.IsChecked)
    @Html.HiddenFor(m => m.Id)
    @Html.LabelFor(m => m.IsChecked, Model.Id)
    

    在你的实际视图中,没有必要循环这个,只需1行代码:

    @Html.EditorFor(x => ViewData.Model)
    

    访问我的blog post了解更多详情 .

  • 5

    这就是我一直在做的事情 .

    视图:

    <input type="checkbox" name="applyChanges" />
    

    控制器:

    var checkBox = Request.Form["applyChanges"];
    
    if (checkBox == "on")
    {
    ...
    }
    

    我发现Html . *帮助器方法在某些情况下并没有那么有用,而且我最好在普通的旧HTML中使用它 . 这是其中之一,想到的另一个是单选按钮 .

    编辑:这是在预览5上,显然是版本之间的YMMV .

  • 3

    Html.CheckBox正在做一些奇怪的事情 - 如果你在结果页面上查看源代码,你就会在每个复选框旁边生成 <input type="hidden" /> ,这解释了你为每个表单元素看到的"true false"值 .

    试试这个,这肯定适用于ASP.NET MVC Beta,因为我刚试过它 .

    把它放在视图中而不是使用Html.CheckBox():

    <% using (Html.BeginForm("ShowData", "Home")) {  %>
      <% foreach (var o in ViewData.Model) { %>
        <input type="checkbox" name="selectedObjects" value="<%=o.Id%>">
        <%= o.Name %>
      <%}%>
      <input type="submit" value="Submit" />
    <%}%>
    

    您的复选框全部称为 selectedObjects ,每个复选框的 value 是相应对象的GUID .

    然后发布到以下控制器操作(或类似的东西,做一些有用的而不是Response.Write())

    public ActionResult ShowData(Guid[] selectedObjects) {
        foreach (Guid guid in selectedObjects) {
            Response.Write(guid.ToString());
        }
        Response.End();
        return (new EmptyResult());
    }
    

    这个例子只会写你检查的框的GUID; ASP.NET MVC将所选复选框的GUID值映射到 Guid[] selectedObjects 参数中,甚至将Request.Form集合中的字符串解析为即时GUID对象,我认为这是相当不错的 .

  • 4

    HtmlHelper添加一个隐藏的输入来通知控制器有关未经检查的状态 . 所以要有正确的检查状态:

    bool bChecked = form[key].Contains("true");
    
  • 0

    如果您想知道为什么他们使用与复选框相同的名称放置隐藏字段,原因如下:

    来自源代码MVCBetaSource \ MVC \ src \ MvcFutures \ Mvc \ ButtonsAndLinkExtensions.cs 的评论

    为复选框渲染一个额外的<input type =“hidden”... /> . 这解决了未在请求中发送未选中复选框的情况 . 发送隐藏的输入可以在提交请求时知道页面上存在复选框 .

    我想在幕后他们需要知道这个用于绑定控制器动作方法上的参数 . 然后,我可以使用三态布尔值(绑定到可以为空的bool参数) . 我没试过,但我希望他们做了什么 .

  • 25

    他们似乎是选择仅读取第一个值,因此选中复选框时为“true”,仅包含隐藏值时为“false” . 这很容易用这样的代码获取:

    model.Property = collection["ElementId"].ToLower().StartsWith("true");
    
  • 0

    @Dylan Beattie很棒的发现!!!我非常感谢你为了进一步扩展,这种技术也适用于View Model方法 . MVC非常酷,它足够聪明,可以通过绑定到View的Model对象的相同名称将Guids数组绑定到属性 . 例:

    视图模型:

    public class SampleViewModel
    {
        public IList<SampleObject> SampleObjectList { get; set; }
        public Guid[] SelectedObjectIds { get; set; }
    
        public class SampleObject
        {
            public Guid Id { get; set; }
            public string Name { get; set; }
        }
    }
    

    视图:

    <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Sample View</h2>
    <table>
        <thead> 
            <tr>
                <th>Checked</th>
                <th>Object Name</th>
            </tr>
        </thead> 
    <% using (Html.BeginForm()) %>
    <%{%>                    
        <tbody>
            <% foreach (var item in Model.SampleObjectList)
               { %>
                <tr>
                    <td><input type="checkbox" name="SelectedObjectIds" value="<%= item.Id%>" /></td>
                    <td><%= Html.Encode(item.Name)%></td>
                </tr>
            <% } %>
        </tbody>
    </table>
    <input type="submit" value="Submit" />
    <%}%>
    

    控制器:

    [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult SampleView(Guid id)
        {
            //Object to pass any input objects to the View Model Builder 
            BuilderIO viewModelBuilderInput = new BuilderIO();
    
            //The View Model Builder is a conglomerate of repositories and methods used to Construct a View Model out of Business Objects
            SampleViewModel viewModel = sampleViewModelBuilder.Build(viewModelBuilderInput);
    
            return View("SampleView", viewModel);
        }
    
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult SampleView(SampleViewModel viewModel)
        {
            // The array of Guids successfully bound to the SelectedObjectIds property of the View Model!
            return View();
        }
    

    任何熟悉View Model理念的人都会高兴,这就像冠军!

  • 0

    我还想指出,您可以为每个复选框命名一个不同的名称,并将该名称作为actionresults参数的一部分 .

    例,

    视图:

    <%= Html.CheckBox("Rs232CheckBox", false, new { @id = "rs232" })%>RS-232
    
     <%= Html.CheckBox("Rs422CheckBox", false, new { @id = "rs422" })%>RS-422
    

    控制器:

    public ActionResults MyAction(bool Rs232CheckBox, bool Rs422CheckBox) {
        ...
    }
    

    由于名称相同,视图中的值将传递给操作 .

    我知道这个解决方案并不适合你的项目,但我想我会把这个想法抛在脑后 .

  • 6
    <input type = "checkbox" name = "checkbox1" /> <label> Check to say hi.</label>
    

    来自控制器:

    [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Index(FormCollection fc)
        {
    
             var s = fc["checkbox1"];
    
             if (s == "on")
             {
                 string x = "Hi";
             }
        }
    
  • 10

    此问题也在1.0版本中发生 . Html.Checkbox()导致添加另一个隐藏字段,其名称/ ID与原始复选框相同 . 当我尝试使用document.GetElemtentsByName()加载一个复选框数组时,你可以猜出事情是如何搞砸的 . 这是一个奇怪的 .

  • 3

    从我可以收集的内容来看,模型不想猜测checked = true或false,我通过在jQuery上设置一个值属性来解决这个问题,然后再提交表单,如下所示:

    $('input[type="checkbox"]').each(function () {
           $(this).attr('value', $(this).is(':checked'));
     });
    

    这样,您不需要隐藏元素来存储复选框的值 .

  • 8

    我知道这个问题是在MVC3没有出来的时候编写的,但是对于那些提出这个问题而且正在使用MVC3的人来说,你可能想要“正确”的方法来做到这一点 .

    虽然我认为做到了整体

    Contains("true");
    

    事情是伟大和干净的,并适用于所有MVC版本,问题是它不考虑文化(好像它在布尔的情况下真的很重要) .

    用于计算bool值的“正确”方法(至少在MVC3中)是使用ValueProvider .

    var value = (bool)ValueProvider.GetValue("key").ConvertTo(typeof(bool));
    

    当我编辑权限时,我在我的一个客户端站点中执行此操作:

    var allPermissionsBase = Request.Params.AllKeys.Where(x => x.Contains("permission_")).ToList();
    var allPermissions = new List<KeyValuePair<int, bool>>();
    
    foreach (var key in allPermissionsBase)
    {
         // Try to parse the key as int
         int keyAsInt;
         int.TryParse(key.Replace("permission_", ""), out keyAsInt);
    
         // Try to get the value as bool
         var value = (bool)ValueProvider.GetValue(key).ConvertTo(typeof(bool));
    }
    

    现在,它的美妙之处在于您可以使用几乎任何简单的类型,甚至可以根据文化(想想金钱,小数等)来正确使用它 .

    ValueProvider是您在这样形成Actions时使用的:

    public ActionResult UpdatePermissions(bool permission_1, bool permission_2)
    

    但是当您尝试动态构建这些列表并检查值时,您将永远不会在编译时知道Id,因此您必须动态处理它们 .

  • 0

    最简单的方法是......

    您设置名称和值 .

    <input type="checkbox" name="selectedProducts" value="@item.ProductId" />@item.Name

    然后提交抓取复选框的值并保存在int数组中 . 那么适当的LinQ函数 . 而已..

    [HttpPost]
            public ActionResult Checkbox(int[] selectedObjects)
            {
                var selected = from x in selectedObjects
                               from y in db
                               where y.ObjectId == x
                               select y;                   
    
                return View(selected);
            }
    
  • 27

    与nautic20的答案相同,只需使用与ViewModel中string / int / enum的集合属性相同名称的MVC默认模型绑定复选框列表 . 这就对了 .

    但有一个问题需要指出 . 在每个复选框组件中,您不应在其中放置“Id”,这将影响MVC模型绑定 .

    以下代码适用于模型绑定:

    <% foreach (var item in Model.SampleObjectList)
           { %>
            <tr>
                <td><input type="checkbox" name="SelectedObjectIds" value="<%= item.Id%>" /></td>
                <td><%= Html.Encode(item.Name)%></td>
            </tr>
     <% } %>
    

    以下代码不会绑定到模型(这里的差异是它为每个复选框分配了id)

    <% foreach (var item in Model.SampleObjectList)
           { %>
            <tr>
                <td><input type="checkbox" name="SelectedObjectIds" id="[some unique key]" value="<%= item.Id%>" /></td>
                <td><%= Html.Encode(item.Name)%></td>
            </tr>
    <% } %>
    
  • 4

    这就是我在使用Html.CheckBox时松散双值的做法(...

    Replace("true,false","true").Split(',')
    

    选中4个框,取消选中,取消选中,选中它变为true,false,false,false,true,false变为true,false,false,true . 正是我需要的

  • 262

    使用复选框HtmlHelper时,我更喜欢使用已发布的复选框表单数据作为数组 . 我不知道为什么,我知道其他方法有效,但我想我更喜欢尽可能地将逗号分隔的字符串视为数组 .

    所以做一个'检查'或真正的测试将是:

    //looking for [true],[false]
    bool isChecked = form.GetValues(key).Contains("true");
    

    做一个错误的检查将是:

    //looking for [false],[false] or [false]
    bool isNotChecked = !form.GetValues(key).Contains("true");
    

    主要区别是使用 GetValues ,因为它返回一个数组 .

  • 95

    只需在 $(document).ready 上执行此操作:

    $('input:hidden').each(function(el) {
        var that = $(this)[0];
        if(that.id.length < 1 ) {
    
            console.log(that.id);
            that.parentElement.removeChild(that);
    
        }
    });
    
  • 4

    我的解决方案是:

    <input type="checkbox"  id="IsNew-checkbox"  checked="checked" />     
    <input type="hidden"  id="IsNew" name="IsNew" value="true"  />      
    <script language="javascript" type="text/javascript" >     
      $('#IsNew-checkbox').click(function () {    
          if ($('#IsNew-checkbox').is(':checked')) {    
              $('#IsNew').val('true');    
          } else {    
              $('#IsNew').val('false');    
           }    
      });   
    </script>
    

    你可以在这里找到更多:http://www.blog.mieten.pl/2010/12/asp-net-mvc-custom-checkbox-as-solution-of-string-was-not-recognized-as-a-valid-boolean/

  • 0

    我有几乎相同的问题,但我的控制器的返回值被其他值阻止 .

    找到一个简单的解决方案,但它似乎有点粗糙 .

    尝试在您的控制器中键入 Viewbag. ,现在给它一个名称,如 Viewbag.Checkbool

    现在切换到View并尝试使用此 @Viewbag.Checkbool ,您将获得Controller的值 .

    我的控制器参数如下所示:

    public ActionResult Anzeigen(int productid = 90, bool islive = true)
    

    我的Checkbox会像这样更新:

    <input id="isLive" type="checkbox" checked="@ViewBag.Value" ONCLICK="window.location.href = '/MixCategory/Anzeigen?isLive=' + isLive.checked.toString()" />
    
  • 0

    使用@mmacaulay,我为bool想出了这个:

    // MVC Work around for checkboxes.
    bool active = (Request.Form["active"] == "on");
    

    如果选中active = true

    如果未选中active = false

相关问题