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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/220020/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-07 22:48:21  来源:igfitidea点击:

How to handle checkboxes in ASP.NET MVC forms?

asp.net-mvcformscheckbox

提问by Dylan Beattie

Caution: This question is over nine years old!

注意:这个问题已经超过九年了!

Your best option is to search for newer questions, or to search the answers below looking for your specific version of MVC, as many answers here are obsolete now.

您最好的选择是搜索较新的问题,或者搜索下面的答案以寻找您的特定 MVC 版本,因为这里的许多答案现在已经过时了。

If you do find an answer that works for your version, please make sure the answer contains the version of MVC you are using.
(The original question starts below)

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



This seems a bit bizarre to me, but as far as I can tell, this is how you do it.

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

I have a collection of objects, and I want users to select one or more of them. This says to me "form with checkboxes." My objects don't have any concept of "selected" (they're rudimentary POCO's formed by deserializing a wcf call). So, I do the following:

我有一组对象,我希望用户选择其中一个或多个。这对我说“带有复选框的表单”。我的对象没有任何“选择”的概念(它们是通过反序列化 wcf 调用形成的基本 POCO)。因此,我执行以下操作:

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

In the view:

在视图中:

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

And, in the controller, this is the only way I can see to figure out what objects the user checked:

而且,在控制器中,这是我可以看到的唯一方法来找出用户检查了哪些对象:

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

Its freaky in the first place, and secondly, for those items the user checked, the FormCollection lists its value as "true false" rather than just true.

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

Obviously, I'm missing something. I think this is built with the idea in mind that the objects in the collection that are acted upon within the html form are updated using UpdateModel()or through a ModelBinder.

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

But my objects aren't set up for this; does that mean that this is the only way? Is there another way to do it?

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

回答by Dylan Beattie

Html.CheckBox is doing something weird - if you view source on the resulting page, you'll see there's an <input type="hidden" />being generated alongside each checkbox, which explains the "true false" values you're seeing for each form element.

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

Try this, which definitely works on ASP.NET MVC Beta because I've just tried it.

试试这个,它绝对适用于 ASP.NET MVC Beta,因为我刚刚尝试过。

Put this in the view instead of using Html.CheckBox():

把它放在视图中而不是使用 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" />
<%}%>

Your checkboxes are all called selectedObjects, and the valueof each checkbox is the GUID of the corresponding object.

您的复选框都称为selectedObjectsvalue每个复选框的 是对应对象的 GUID。

Then post to the following controller action (or something similar that does something useful instead of Response.Write())

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

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

This example will just write the GUIDs of the boxes you checked; ASP.NET MVC maps the GUID values of the selected checkboxes into the Guid[] selectedObjectsparameter for you, and even parses the strings from the Request.Form collection into instantied GUID objects, which I think is rather nice.

此示例将只写入您选中的框的 GUID;ASP.NET MVC 将选中复选框的 GUID 值映射到Guid[] selectedObjects参数中,甚至将 Request.Form 集合中的字符串解析为实例化的 GUID 对象,我认为这相当不错。

回答by Andrea Balducci

HtmlHelper adds an hidden input to notify the controller about Unchecked status. So to have the correct checked status:

HtmlHelper 添加了一个隐藏的输入来通知控制器有关 Unchecked 状态。因此,要获得正确的检查状态:

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

回答by Simon_Weaver

In case you're wondering WHY they put a hidden field in with the same name as the checkbox the reason is as follows :

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

Comment from the sourcecode MVCBetaSource\MVC\src\MvcFutures\Mvc\ButtonsAndLinkExtensions.cs

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

Render an additional <input type="hidden".../>for checkboxes. This addresses scenarios where unchecked checkboxes are not sent in the request. Sending a hidden input makes it possible to know that the checkbox was present on the page when the request was submitted.

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

I guess behind the scenes they need to know this for binding to parameters on the controller action methods. You could then have a tri-state boolean I suppose (bound to a nullable bool parameter). I've not tried it but I'm hoping thats what they did.

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

回答by Simon_Weaver

You should also use <label for="checkbox1">Checkbox 1</label>because then people can click on the label text as well as the checkbox itself. Its also easier to style and at least in IE it will be highlighted when you tab through the page's controls.

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

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

This is not just a 'oh I could do it' thing. Its a significant user experience enhancement. Even if not all users know they can click on the label many will.

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

回答by Shawn Mclean

I'm surprised none of these answers used the built in MVC features for this.

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

I wrote a blog post about this here, which even actually links the labels to the checkbox. I used the EditorTemplatefolder to accomplish this in a clean and modular way.

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

You will simply end up with a new file in the EditorTemplate folder that looks like this:

您将简单地在 EditorTemplate 文件夹中得到一个新文件,如下所示:

@model SampleObject

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

in your actual view, there will be no need to loop this, simply 1 line of code:

在您的实际视图中,不需要循环这个,只需 1 行代码:

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

Visit my blog postfor more details.

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

回答by mmacaulay

Here's what I've been doing.

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

View:

看法:


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

Controller:

控制器:


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

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

I found the Html.* helper methods not so useful in some cases, and that I was better off doing it in plain old HTML. This being one of them, the other one that comes to mind is radio buttons.

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

Edit: this is on Preview 5, obviously YMMV between versions.

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

回答by Fluffy

They appear to be opting to read the first value only, so this is "true" when the checkbox is checked, and "false" when only the hidden value is included. This is easily fetched with code like this:

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

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

回答by nautic20

@Dylan Beattie Great Find!!! I Thank you much. To expand even further, this technique also works perfect with the View Model approach. MVC is so cool, it's smart enough to bind an array of Guids to a property by the same name of the Model object bound to the View. Example:

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

ViewModel:

视图模型:

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

View:

看法:

<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" />
<%}%>                    

Controller:

控制器:

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

Anyone familiar with the View Model philosophy will rejoice, this works like a Champ!

任何熟悉 View Model 哲学的人都会高兴,这就像冠军一样!

回答by Darcy

I'd also like to point out that you can name each checkbox a different name, and have that name part of the actionresults parameters.

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

Example,

例子,

View:

看法:

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

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

Controller:

控制器:

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

The values from the view are passed to the action since the names are the same.

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

I know this solution isn't ideal for your project, but I thought I'd throw the idea out there.

我知道这个解决方案不适合您的项目,但我想我会放弃这个想法。

回答by bluwater2001

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

From the Controller:

从控制器:

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Index(FormCollection fc)
    {

         var s = fc["checkbox1"];

         if (s == "on")
         {
             string x = "Hi";
         }
    }