Comment gérer les cases à cocher dans les formulaires ASP.NET MVC?

Attention: cette question a plus de neuf ans!

Votre meilleure option est de rechercher des questions plus récentes ou de rechercher les réponses ci-dessous à la recherche de votre version spécifique de MVC, car de nombreuses réponses sont obsolètes maintenant.

Si vous trouvez une réponse adaptée à votre version, veuillez vous assurer que la réponse contient la version de MVC que vous utilisez.
(La question initiale commence ci-dessous)


Cela me semble un peu bizarre, mais pour autant que je sache, c’est comme ça que vous le faites.

J’ai une collection d’objects et je veux que les utilisateurs en sélectionnent un ou plusieurs. Cela me dit “forme avec des cases à cocher”. Mes objects n’ont aucun concept de “sélectionné” (ils sont rudimentaires formés par désérialisation d’un appel wcf). Donc, je fais ce qui suit:

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

Dans la vue:

        

Et, dans le contrôleur, c’est la seule façon de voir quels objects l’utilisateur a vérifiés:

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

Son freaky en premier lieu, et deuxièmement, pour ces éléments que l’utilisateur a coché, le FormCollection répertorie sa valeur comme “true false” plutôt que simplement vrai.

De toute évidence, il me manque quelque chose. Je pense que cela est construit en ayant l’idée que les objects de la collection qui sont UpdateModel() dans le formulaire HTML sont mis à jour à l’aide de UpdateModel() ou d’un ModelBinder.

Mais mes objects ne sont pas configurés pour cela; Est-ce que cela signifie que c’est la seule façon? Y a-t-il une autre façon de le faire?

Html.CheckBox fait quelque chose de bizarre – si vous affichez la source sur la page résultante, vous verrez qu’il y a un généré à côté de chaque case à cocher, ce qui explique les “vraies fausses” valeurs que vous voyez pour chaque élément de forme.

Essayez ceci, qui fonctionne définitivement sur ASP.NET MVC Beta parce que je viens de l’essayer.

Placez ceci dans la vue au lieu d’utiliser Html.CheckBox ():

 <% using (Html.BeginForm("ShowData", "Home")) { %> <% foreach (var o in ViewData.Model) { %>  <%= o.Name %> <%}%>  <%}%> 

Vos cases à cocher sont toutes appelées selectedObjects et la value de chaque case à cocher est le GUID de l’object correspondant.

Publiez ensuite dans l’action de contrôleur suivante (ou quelque chose de similaire qui fait quelque chose d’utile à la place de Response.Write ())

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

Cet exemple va simplement écrire les GUID des cases que vous avez cochées; ASP.NET MVC mappe les valeurs GUID des cases à cocher sélectionnées dans le paramètre Guid[] selectedObjects pour vous, et parsing même les chaînes de la collection Request.Form en objects GUID instantanés, ce qui est plutôt intéressant.

HtmlHelper ajoute une entrée masquée pour informer le contrôleur de l’état non vérifié. Donc, pour avoir le bon état vérifié:

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

Si vous vous demandez POURQUOI ils ont mis un champ caché avec le même nom que la case à cocher, la raison est la suivante:

Commentaire du code source MVCBetaSource \ MVC \ src \ MvcFutures \ Mvc \ ButtonsAndLinkExtensions.cs

Rendre un supplémentaire pour les cases à cocher. Cela concerne les scénarios où les cases non cochées ne sont pas envoyées dans la demande. L’envoi d’une entrée masquée permet de savoir que la case à cocher était présente sur la page lors de la soumission de la demande.

Je suppose que, dans les coulisses, ils doivent le savoir pour se connecter aux parameters des méthodes d’action du contrôleur. Vous pouvez alors avoir un booléen à trois états que je suppose (lié à un paramètre bool nullable). Je n’ai pas essayé mais j’espère que c’est ce qu’ils ont fait.

Vous devez également utiliser car les utilisateurs peuvent alors cliquer sur le texte de l’étiquette ainsi que sur la case à cocher elle-même. Il est également plus facile à coiffer et au moins dans IE, il sera mis en évidence lorsque vous tabulez les contrôles de la page.

 <%= Html.CheckBox("cbNewColors", true) %> 

Ce n’est pas juste une chose “oh je pourrais le faire”. C’est une amélioration significative de l’expérience utilisateur. Même si tous les utilisateurs ne savent pas qu’ils peuvent cliquer sur l’étiquette, beaucoup le feront.

Je suis surpris qu’aucune de ces réponses n’utilise les fonctionnalités intégrées de MVC.

J’ai écrit un article sur ce sujet ici , qui relie même les étiquettes à la case à cocher. J’ai utilisé le dossier EditorTemplate pour y parvenir d’une manière propre et modulaire.

Vous allez simplement vous retrouver avec un nouveau fichier dans le dossier EditorTemplate qui ressemble à ceci:

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

dans votre vue actuelle, il ne sera pas nécessaire de boucler ceci, simplement une ligne de code:

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

Visitez mon blog pour plus de détails.

Voici ce que j’ai fait

Vue:


 

Manette:

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

J’ai trouvé les méthodes d’assistance Html. * Pas très utiles dans certains cas, et il valait mieux que je le fasse en HTML. Cela étant, l’autre qui vient à l’esprit est celui des boutons radio.

Edit: c’est sur Preview 5, évidemment YMMV entre les versions.

Ils semblent choisir de ne lire que la première valeur, ce qui signifie “true” lorsque la case est cochée et “false” lorsque seule la valeur masquée est incluse. Ceci est facilement récupéré avec du code comme celui-ci:

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

@Dylan Beattie Great Find !!! Je vous remercie beaucoup. Pour aller encore plus loin, cette technique fonctionne également parfaitement avec l’approche du modèle de vue. MVC est tellement cool qu’il est assez intelligent de lier un tableau de Guids à une propriété du même nom que l’object Model lié à View. Exemple:

ViewModel:

 public class SampleViewModel { public IList SampleObjectList { get; set; } public Guid[] SelectedObjectIds { get; set; } public class SampleObject { public Guid Id { get; set; } public ssortingng Name { get; set; } } } 

Vue:

  

Sample View

<% using (Html.BeginForm()) %> <%{%> <% foreach (var item in Model.SampleObjectList) { %> <% } %>
Checked Object Name
<%= Html.Encode(item.Name)%>
<%}%>

Manette:

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

Toute personne familière avec la philosophie de View Model se réjouira, cela fonctionne comme un champion!

Je tiens également à souligner que vous pouvez nommer chaque case à cocher sous un nom différent et que ce nom fait partie des parameters de l’action.

Exemple,

Vue:

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

Manette:

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

Les valeurs de la vue sont transmises à l’action car les noms sont identiques.

Je sais que cette solution n’est pas idéale pour votre projet, mais je pensais lancer l’idée.

   

Du contrôleur:

  [AcceptVerbs(HttpVerbs.Post)] public ActionResult Index(FormCollection fc) { var s = fc["checkbox1"]; if (s == "on") { ssortingng x = "Hi"; } } 

Ce problème se produit également dans la version 1.0. Html.Checkbox () provoque l’ajout d’un autre champ masqué avec le même nom / identifiant que celui de votre case d’origine. Et comme j’essayais de charger un tableau de cases à cocher en utilisant document.GetElemtentsByName (), vous pouvez deviner comment les choses se sont gâchées. C’est bizarre.

D’après ce que je peux rassembler, le modèle ne veut pas deviner s’il est vérifié = true ou false, j’ai contourné cela en définissant un atsortingbut value sur l’élément checkbox avec jQuery avant de soumettre le formulaire comme ceci:

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

De cette façon, vous n’avez pas besoin d’un élément caché pour stocker la valeur de la case à cocher.

Je sais que cette question a été écrite alors que MVC3 n’était pas sortie, mais pour toute personne qui aborde cette question et utilise MVC3, vous pouvez choisir la méthode “correcte”.

Bien que je pense que faire tout

 Contains("true"); 

La chose est géniale et propre, et fonctionne sur toutes les versions de MVC, le problème est que cela ne prend pas en compte la culture (comme si cela était vraiment important dans le cas d’un bool).

La méthode “correcte” pour déterminer la valeur d’un bool, au moins dans MVC3, consiste à utiliser ValueProvider.

 var value = (bool)ValueProvider.GetValue("key").ConvertTo(typeof(bool)); 

Je le fais sur l’un des sites de mon client lorsque je modifie les permissions:

 var allPermissionsBase = Request.Params.AllKeys.Where(x => x.Contains("permission_")).ToList(); var allPermissions = new List>(); 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)); } 

Maintenant, la beauté de ceci est que vous pouvez utiliser ceci avec à peu près n’importe quel type simple, et cela sera même correct basé sur la culture (pensez à l’argent, aux décimales, etc.).

Le ValueProvider est ce qui est utilisé lorsque vous créez vos actions comme ceci:

 public ActionResult UpdatePermissions(bool permission_1, bool permission_2) 

mais lorsque vous essayez de construire dynamicment ces listes et de vérifier les valeurs, vous ne connaîtrez jamais l’ID à la compilation, vous devez donc les traiter à la volée.

La façon la plus simple de le faire est donc …

Vous définissez le nom et la valeur.

@item.Name

Ensuite, lors de la soumission, saisissez les valeurs des cases à cocher et sauvegardez-les dans un tableau int. puis la fonction LinQ appropriée. C’est tout..

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

Identique à la réponse de nautic20, utilisez simplement la liste de cases à cocher MVC par défaut avec le même nom qu’une propriété de collection de ssortingng / int / enum dans ViewModel. C’est ça.

Mais un problème doit être souligné. Dans chaque composant de la case à cocher, vous ne devez pas y mettre “Id”, ce qui affectera la liaison du modèle MVC.

Le code suivant fonctionnera pour la liaison de modèle:

  <% foreach (var item in Model.SampleObjectList) { %>   <%= Html.Encode(item.Name)%>  <% } %> 

Les codes suivants ne seront pas liés au modèle (la différence ici est-elle assignée à chaque case à cocher)

 <% foreach (var item in Model.SampleObjectList) { %>   <%= Html.Encode(item.Name)%>  <% } %> 

c’est ce que j’ai fait pour perdre les valeurs doubles lors de l’utilisation de Html.CheckBox (…

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

avec 4 cases cochées, non cochées, décochées, cochées, il devient vrai, faux, faux, faux, vrai, faux en vrai, faux, faux, vrai. juste ce dont j’avais besoin

Que diriez-vous quelque chose comme ça?

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

Lorsque vous utilisez la case à cocher HtmlHelper, je préfère de beaucoup travailler avec les données de formulaire de case à cocher publiées en tant que tableau. Je ne sais pas vraiment pourquoi, je sais que les autres méthodes fonctionnent, mais je pense que je préfère simplement traiter les chaînes séparées par des virgules comme un tableau autant que possible.

Donc, faire un test “vérifié” ou vrai serait:

 //looking for [true],[false] bool isChecked = form.GetValues(key).Contains("true"); 

Faire un faux chèque serait:

 //looking for [false],[false] or [false] bool isNotChecked = !form.GetValues(key).Contains("true"); 

La principale différence est d’utiliser GetValues car cela retourne en tant que tableau.

Faites-le simplement sur $(document).ready :

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

Ma solution est la suivante:

    

Plus vous pouvez trouver ici: http://www.blog.mieten.pl/2010/12/asp-net-mvc-custom-checkbox-as-solution-of-ssortingng-was-not-recognized-as-a- valid-boolean /

J’ai eu presque le même problème mais la valeur de retour de mon contrôleur a été bloquée avec d’autres valeurs.

J’ai trouvé une solution simple mais cela semble un peu rude.

Essayez de taper Viewbag. dans votre contrôleur et maintenant vous lui donnez un nom comme Viewbag.Checkbool

@Viewbag.Checkbool maintenant à la vue et essayez ceci @Viewbag.Checkbool avec ceci vous obtiendrez la valeur du contrôleur.

Mes parameters de contrôleur ressemblent à ceci:

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

et ma case à cocher se mettra à jour comme ceci:

  

En utilisant @mmacaulay, je suis venu avec ceci pour bool:

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

Si coché actif = vrai

Si décoché actif = faux