如何处理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)%> <%= 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