246

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

您最好的选择是搜索较新的问题,或者搜索下面的答案以查找您的特定 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 更新的。

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

4

22 回答 22

262

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

试试这个,它肯定适用于 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" />
<%}%>

您的复选框都称为selectedObjectsvalue每个复选框的 是相应对象的 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 对象,我认为这很不错。

于 2008-10-20T21:49:11.987 回答
95

HtmlHelper 添加了一个隐藏的输入来通知控制器 Unchecked 状态。所以要有正确的检查状态:

bool bChecked = form[key].Contains("true");
于 2009-01-12T15:55:40.237 回答
54

如果您想知道为什么他们会在其中放置一个与复选框同名的隐藏字段,原因如下:

来自源代码的注释 MVCBetaSource\MVC\src\MvcFutures\Mvc\ ButtonsAndLinkExtensions.cs

<input type="hidden".../>为复选框渲染一个附加信息。这解决了未在请求中发送未选中复选框的情况。发送隐藏的输入可以知道提交请求时该复选框已出现在页面上。

我想在幕后他们需要知道这一点才能绑定到控制器操作方法上的参数。然后你可以有一个我想的三态布尔值(绑定到一个可为空的 bool 参数)。我没有尝试过,但我希望这就是他们所做的。

于 2009-01-26T09:29:49.207 回答
49

您还应该使用<label for="checkbox1">Checkbox 1</label>,因为人们可以单击标签文本以及复选框本身。它的样式也更容易,至少在 IE 中,当您通过页面控件进行选项卡时,它会突出显示。

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

这不仅仅是“哦,我能做到”的事情。它显着增强了用户体验。即使不是所有用户都知道他们可以点击很多人会点击的标签。

于 2009-01-26T09:19:13.643 回答
27

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

我在这里写了一篇关于这个的博客文章,它甚至实际上将标签链接到了复选框。我使用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)

访问我的博客文章了解更多详情。

于 2011-10-16T03:31:12.047 回答
25

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

看法:


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

控制器:


var checkBox = Request.Form["applyChanges"];

if (checkBox == "on")
{
...
}

我发现 Html.* 辅助方法在某些情况下不是很有用,而且我最好用普通的旧 HTML 来做。这是其中之一,另一个想到的是单选按钮。

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

于 2008-10-20T21:37:58.483 回答
10

他们似乎选择只读取第一个值,所以当复选框被选中时这是“真”,而当只包含隐藏值时这是“假”。这很容易用这样的代码获取:

model.Property = collection["ElementId"].ToLower().StartsWith("true");
于 2010-03-20T20:36:06.117 回答
8

@Dylan Beattie 很棒的发现!!!我非常感谢你。为了进一步扩展,这种技术也可以完美地与视图模型方法配合使用。MVC 太酷了,它很聪明,可以将 Guid 数组绑定到与绑定到 View 的 Model 对象同名的属性。例子:

视图模型:

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 哲学的人都会很高兴,这就像一个冠军!

于 2010-06-04T15:24:48.990 回答
6

我还想指出,您可以为每个复选框命名一个不同的名称,并将该名称作为 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) {
    ...
}

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

我知道这个解决方案不适合你的项目,但我想我会把这个想法扔在那里。

于 2010-03-22T14:48:25.790 回答
5
<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";
         }
    }
于 2010-06-21T19:41:28.580 回答
4

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

于 2010-01-18T11:23:28.397 回答
4

据我所知,模型不想猜测checked = true还是false,我通过在提交表单之前使用jQuery在checkbox元素上设置一个value属性来解决这个问题:

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

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

于 2012-05-22T21:32:21.343 回答
4

我知道这个问题是在 MVC3 还没有出来的时候写的,但是对于任何遇到这个问题并使用 MVC3 的人,你可能想要“正确”的方式来做到这一点。

虽然我认为做整个

Contains("true");

东西很棒而且很干净,适用于所有 MVC 版本,问题是它没有考虑文化(好像在布尔的情况下它真的很重要)。

至少在 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 是在您形成如下操作时使用的:

public ActionResult UpdatePermissions(bool permission_1, bool permission_2)

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

于 2012-06-14T23:07:43.770 回答
3

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

您设置名称和值。

<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);
        }
于 2012-01-05T16:10:31.090 回答
3

与 nautic20 的答案相同,只需使用与 ViewModel 中字符串/整数/枚举的集合属性同名的 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>
<% } %>
于 2014-03-11T17:05:00.417 回答
2

这就是我在使用 Html.CheckBox(...

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

选中 4 个框,未选中,未选中,选中它会变成 true,false,false,false,true,false 变成 true,false,false,true。正是我需要的

于 2010-10-22T16:07:08.947 回答
0

这样的事情怎么样?

bool isChecked = false;
if (Boolean.TryParse(Request.Form.GetValues(”chkHuman”)[0], out isChecked) == false)
    ModelState.AddModelError(”chkHuman”, “Nice try.”);
于 2010-11-11T20:49:15.830 回答
0

我的解决方案是:

<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-有效布尔值/

于 2010-12-29T10:20:55.973 回答
0

使用复选框 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"); 

主要区别是使用GetValuesas this 作为数组返回。

于 2011-04-20T22:25:36.203 回答
0

只需在以下位置执行此操作$(document).ready

$('input:hidden').each(function(el) {
    var that = $(this)[0];
    if(that.id.length < 1 ) {

        console.log(that.id);
        that.parentElement.removeChild(that);

    }
});
于 2011-08-10T15:38:26.103 回答
0

我遇到了几乎相同的问题,但是我的控制器的返回值被其他值阻止了。

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

尝试输入Viewbag.你的控制器,现在你给它起一个名字Viewbag.Checkbool

现在切换到视图并尝试此操作@Viewbag.Checkbool,您将从控制器中获取值。

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

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

我的复选框将像这样更新:

<input id="isLive" type="checkbox" checked="@ViewBag.Value" ONCLICK="window.location.href = '/MixCategory/Anzeigen?isLive=' + isLive.checked.toString()" />
于 2013-04-17T08:15:22.103 回答
0

使用@mmacaulay ,我想出了这个布尔:

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

如果选中活动 = true

如果未选中 active = false

于 2014-02-25T23:02:14.640 回答