如何处理ASP.NET MVC窗体中的checkbox?

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

您最好的select是search更新的问题,或者在下面search您的具体版本的MVC,因为许多答案现在已经过时了。

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


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

我有一个对象的集合,我希望用户select一个或多个。 这对我说“与checkboxforms”。 我的对象没有任何“select”的概念(它们是通过反序列化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将它的值列为“true false”,而不仅仅是true。

显然,我错过了一些东西。 我认为这是build立在脑海中的想法集合中的对象是在HTML表单中更新使用UpdateModel()或通过ModelBinder。

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

Html.CheckBox正在做一些奇怪的事情 – 如果你在结果页面上查看源代码,你会发现在每个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" /> <%}%> 

您的checkbox都被称为selectedObjects ,每个checkbox的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将所选checkbox的GUID值映射到Guid[] selectedObjects参数中,甚至将Request.Form集合中的stringparsing为即时GUID对象,我认为这很好。

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

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

如果你想知道为什么他们把一个隐藏的领域与checkbox相同的名字,原因如下:

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

为checkbox呈现额外的<input type="hidden".../> 。 这解决了在请求中未发送checkbox的场景。 发送一个隐藏的input可以知道提交请求时,该页面上出现了checkbox。

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

您还应该使用<label for="checkbox1">Checkbox 1</label>因为人们可以点击标签文本以及checkbox本身。 它也更容易的风格,至less在IE浏览器,它会突出显示,当你通过页面的控制选项卡。

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

这不仅仅是一个'我可以做到'的事情。 其重要的用户体验增强。 即使不是所有的用户都知道他们可以点击标签上的许多意愿。

我很惊讶这些答案都没有使用内置的MVCfunction。

我在这里写了一篇关于这个的博客文章,甚至把标签链接到checkbox。 我用EditorTemplate文件夹以干净和模块化的方式来完成这个任务。

您将只需在EditorTemplate文件夹中添加一个新文件,如下所示:

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

在你的实际视图中,不需要循环,只需要一行代码:

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

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

这是我一直在做的。

视图:

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

控制器:

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

在某些情况下,我发现Html。* helper方法不是非常有用,而且我最好在普通的旧HTML中使用它。 这是其中之一,另一个想到的是单选button。

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

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

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

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

视图模型:

 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(); } 

任何熟悉视图模型哲学的人都会高兴,这就像一个冠军!

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

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

我知道这个解决scheme对于你的项目来说并不理想,但是我想我会把这个想法放在那里。

 <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"; } } 

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

从我可以收集的,模型不想猜测是否checked = true或false,我通过在jQuery的checkbox元素上设置一个值属性来解决这个问题,然后提交这样的表单:

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

这样,你不需要一个隐藏的元素来存储checkbox的值。

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

虽然我认为这样做是完整的

 Contains("true"); 

事情是伟大的,干净的,并在所有MVC版本的作品,问题是,它不考虑到文化(如果真的很重要的情况下布尔)。

至less在MVC3中,找出bool值的“正确”方法是使用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)); } 

现在,这个美丽的东西就可以用于任何简单的types,甚至可以根据文化(比如金钱,小数等等)来使用它。

ValueProvider是当你像这样形成你的动作时使用的:

 public ActionResult UpdatePermissions(bool permission_1, bool permission_2) 

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

和nautic20的答案一样,只要简单地使用MVC默认模型绑定checkbox列表作为ViewModel中string / int / enum的集合属性。 这就对了。

但有一个问题需要指出。 在每个checkbox组件中,您都不应该放入“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> <% } %> 

以下代码将不会绑定到模型(这里的区别是它为每个checkbox分配了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> <% } %> 

这是我做了什么,当使用Html.CheckBox(…

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

检查4盒,未检查,未检查,检查它变为真,假,假,假,真,假为真,假,假,真。 正是我所需要的

最简单的方法是…

您设置名称和值。

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

然后提交抓取checkbox的值并保存在一个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); } 

这样的事情呢?

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

当使用checkboxHtmlHelper时,我更喜欢使用已发布的checkbox表单数据作为数组。 我真的不知道为什么,我知道其他方法的工作,但我认为我只是喜欢尽可能将逗号分隔的string作为一个数组。

所以做一个“检查”或真正的testing将是:

 //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因为它以数组forms返回。

只要在$(document).ready上做这个:

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

我的解决scheme是:

 <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> 

更多你可以在这里find: http : //www.blog.mieten.pl/2010/12/asp-net-mvc-custom-checkbox-as-solution-of-string-was-not-recognized-as-a-有效布尔/

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

find一个简单的解决scheme,但似乎有点粗糙。

尝试键入Viewbag. 在你的Controller中,现在你给它一个像Viewbag.Checkbool这样的名字

现在切换到视图,并用这个@Viewbag.Checkbool来试@Viewbag.Checkbool ,你将得到控制器的值。

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

 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()" /> 

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

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

如果选中active = true

如果未选中active = false