asp.net mvc - example - ¿Cómo manejar las casillas de verificación en los formularios MVC de ASP.NET?




checkboxfor in mvc 5 razor example (15)

¿Qué tal algo como esto?

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

Precaución: ¡Esta pregunta tiene más de nueve años!

Su mejor opción es buscar nuevas preguntas o buscar las respuestas a continuación en busca de su versión específica de MVC, ya que muchas respuestas están obsoletas ahora.

Si encuentra una respuesta que funcione para su versión, asegúrese de que contenga la versión de MVC que está usando.
(La pregunta original comienza abajo)

Esto me parece un poco extraño, pero por lo que puedo decir, así es como lo haces.

Tengo una colección de objetos, y quiero que los usuarios seleccionen uno o más de ellos. Esto me dice "forma con casillas de verificación". Mis objetos no tienen ningún concepto de "seleccionado" (son POCO rudimentarios formados por la deserialización de una llamada wcf). Entonces, hago lo siguiente:

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

En la vista:

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

Y, en el controlador, esta es la única manera que puedo ver para averiguar qué objetos verificó el usuario:

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

Es extraño en primer lugar, y en segundo lugar, para aquellos elementos que el usuario verificó, FormCollection muestra su valor como "verdadero falso" en lugar de solo verdadero.

Obviamente, me estoy perdiendo algo. Creo que esto se ha creado teniendo en cuenta la idea de que los objetos de la colección en los que se actúa en el formulario html se actualizan mediante UpdateModel() o mediante un ModelBinder.

Pero mis objetos no están configurados para esto; ¿Eso significa que esta es la única manera? ¿Hay otra manera de hacerlo?


@Dylan Beattie Great Find !!! Muchas gracias. Para ampliar aún más, esta técnica también funciona a la perfección con el enfoque del modelo de vista. MVC es genial, es lo suficientemente inteligente como para unir una matriz de Guids a una propiedad con el mismo nombre del objeto Modelo vinculado a la Vista. Ejemplo:

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

Ver:

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

Controlador:

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

Cualquiera que esté familiarizado con la filosofía Ver modelo se alegrará, ¡esto funciona como un campeón!


De lo que puedo recopilar, el modelo no quiere adivinar si está marcado = verdadero o falso, resolví esto configurando un atributo de valor en el elemento de casilla de verificación con jQuery antes de enviar el formulario de esta manera:

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

De esta manera, no necesita un elemento oculto solo para almacenar el valor de la casilla de verificación.


En caso de que se pregunte POR QUÉ ponen un campo oculto con el mismo nombre que la casilla de verificación, el motivo es el siguiente:

Comentario del código fuente MVCBetaSource \ MVC \ src \ MvcFutures \ Mvc \ ButtonsAndLinkExtensions.cs

Renderice un <input type="hidden".../> adicional para las casillas de verificación. Esto aborda los escenarios en los que las casillas de verificación no seleccionadas no se envían en la solicitud. El envío de una entrada oculta permite saber que la casilla de verificación estaba presente en la página cuando se envió la solicitud.

Supongo que entre bastidores necesitan saber esto para vincular los parámetros en los métodos de acción del controlador. Entonces podría tener un booleano tri-estatal, supongo (vinculado a un parámetro bool que admite nulos). No lo he intentado pero espero que eso sea lo que hicieron.


Esto es lo que he estado haciendo.

Ver:


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

Controlador:


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

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

Encontré que los métodos de ayuda Html. * No eran tan útiles en algunos casos, y que era mejor hacerlo en HTML antiguo. Este es uno de ellos, el otro que viene a la mente son los botones de radio.

Edición: esto está en la Vista previa 5, obviamente YMMV entre versiones.


Html.CheckBox está haciendo algo extraño: si ve el código fuente en la página resultante, verá que se genera un <input type="hidden" /> junto a cada casilla de verificación, lo que explica los valores "verdaderos falsos" que está viendo. para cada elemento de la forma.

Prueba esto, que definitivamente funciona en ASP.NET MVC Beta porque lo acabo de probar.

Ponga esto en la vista en lugar de usar 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" />
<%}%>

Sus casillas de verificación se denominan selectedObjects , y el value de cada casilla de verificación es el GUID del objeto correspondiente.

Luego publique en la siguiente acción del controlador (o algo similar que haga algo útil en lugar de Response.Write ())

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

Este ejemplo solo escribirá los GUID de las casillas que marcó; ASP.NET MVC asigna los valores GUID de las casillas de verificación seleccionadas en el parámetro Guid[] selectedObjects para usted, e incluso analiza las cadenas de la colección Request.Form en objetos GUID instantáneos, lo que creo que es bastante bueno.


Igual que la respuesta de nautic20, simplemente use la lista de casilla de verificación de enlace del modelo por defecto de MVC con el mismo nombre que una propiedad de colección de string / int / enum en ViewModel. Eso es.

Pero hay que señalar una cuestión. En cada componente de la casilla de verificación, no debe poner "Id" en él, lo que afectará el enlace del modelo MVC.

El siguiente código funcionará para el enlace de modelos:

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

Los siguientes códigos no serán vinculantes al modelo (la diferencia aquí es su ID asignada para cada casilla de verificación)

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

La forma más fácil de hacerlo es tan ...

Establece el nombre y el valor.

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

Luego, al enviar, tome los valores de las casillas de verificación y guárdelos en una matriz int. entonces la función LinQ apropiada. Eso es..

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

Mi solución es:

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

Puede encontrar más información aquí: http://www.blog.mieten.pl/2010/12/asp-net-mvc-custom-checkbox-as-solution-of-string-was-not-recognized-as-a-valid-boolean/


Parece que están optando por leer solo el primer valor, por lo que esto es "verdadero" cuando la casilla está marcada, y "falso" cuando solo se incluye el valor oculto. Esto es fácil de obtener con código como este:

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

Solo haz esto en $(document).ready :

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

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

    }
});

También debe usar <label for="checkbox1">Checkbox 1</label> porque las personas pueden hacer clic en el texto de la etiqueta así como en la propia casilla de verificación. También es más fácil de diseñar y, al menos en IE, se resaltará cuando pases por los controles de la página.

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

Esto no es solo una cosa de 'oh podría hacerlo'. Es una mejora significativa de la experiencia del usuario. Incluso si no todos los usuarios saben que pueden hacer clic en la etiqueta, muchos lo harán.


Tuve casi el mismo problema pero el valor de retorno de mi controlador fue bloqueado con otros valores.

Encontré una solución simple pero parece un poco rudo.

Intenta escribir Viewbag. en su controlador y ahora le da un nombre como Viewbag.Checkbool

Ahora cambie a la Vista y pruebe este @Viewbag.Checkbool con esto obtendrá el valor del Controlador.

Mis parámetros de controlador se ven así:

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

y mi casilla de verificación se actualizará así:

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

Usando @mmacaulay, se me ocurrió esto para bool:

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

Si está marcado activo = verdadero

Si no está activo activo = falso


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

Desde el controlador:

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

         var s = fc["checkbox1"];

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




checkbox