246 votes

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

Attention : Cette question a plus de neuf ans !

La meilleure option est de rechercher des questions plus récentes, ou de rechercher les réponses ci-dessous en fonction de votre version spécifique de MVC, car de nombreuses réponses sont désormais obsolètes.

Si vous trouvez une réponse qui fonctionne pour votre version, veuillez vous assurer que la réponse contient la version de MVC que vous utilisez.
(La question originale commence ci-dessous)


Cela me semble un peu bizarre, mais d'après ce que je sais, c'est comme ça qu'il faut faire.

J'ai une collection d'objets et je veux que les utilisateurs puissent sélectionner un ou plusieurs d'entre eux. Cela me dit "formulaire avec cases à cocher". Mes objets n'ont aucun concept de "sélectionné" (ce sont des POCO rudimentaires formés par la désérialisation d'un appel wcf). Donc, je fais ce qui suit :

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

Dans la vue :

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

Et, dans le contrôleur, c'est le seul moyen que je vois pour savoir quels objets l'utilisateur a coché :

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

D'abord, c'est bizarre, et ensuite, pour les éléments que l'utilisateur a cochés, le FormCollection liste sa valeur comme "true false" plutôt que juste true.

Manifestement, je rate quelque chose. Je pense qu'il est construit avec l'idée en tête que les objets de la collection sur lesquels on agit dans le formulaire html sont mis à jour à l'aide de la fonction UpdateModel() ou à travers un ModelBinder.

Mais mes objets ne sont pas configurés pour cela ; cela signifie-t-il que c'est la seule façon de procéder ? Existe-t-il un autre moyen de procéder ?

2 votes

D'autres personnes pourraient trouver cette solution utile : stackoverflow.com/questions/3291501/

262voto

Dylan Beattie Points 23222

Html.CheckBox fait quelque chose de bizarre - si vous affichez la source de la page résultante, vous verrez qu'il y a un fichier <input type="hidden" /> est généré à côté de chaque case à cocher, ce qui explique les valeurs "vrai-faux" que vous voyez pour chaque élément du formulaire.

Essayez ceci, qui fonctionne certainement sur ASP.NET MVC Beta car je viens de l'essayer.

Mettez ceci dans la vue au lieu d'utiliser 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" />
<%}%>

Vos cases à cocher s'appellent toutes selectedObjects et le value de chaque case à cocher est le GUID de l'objet correspondant.

Ensuite, envoyez un message à l'action de contrôleur suivante (ou quelque chose de similaire qui fait quelque chose d'utile au lieu de Response.Write())

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

Dans cet exemple, nous nous contenterons d'écrire les GUID des cases que vous avez cochées ; ASP.NET MVC fait correspondre les valeurs GUID des cases à cocher sélectionnées dans le champ Guid[] selectedObjects pour vous, et analyse même les chaînes de la collection Request.Form en objets GUID instanciés, ce qui est plutôt bien.

0 votes

Ouaip ! C'est aussi ce que j'ai dû faire pour mes candidatures !

70 votes

Wtf. des champs de saisie cachés avec le MEME nom que le contrôle. c'est ViewState 2.0 !

3 votes

Ceci est également présent dans la version 1.0. Regardez la réponse soumise par @andrea-balducci qui vous donne une façon intelligente de gérer ce problème. Si la case à cocher n'est pas cochée, le texte récupéré doit être 'false false' - c'est une bonne solution de rechange pour tenir compte des navigateurs en état de mort cérébrale...

95voto

Andrea Balducci Points 1937

HtmlHelper ajoute une entrée cachée pour notifier au contrôleur le statut "Unchecked". Ainsi pour avoir le statut correct coché :

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

1 votes

C'est l'approche la plus simple de ce problème et c'est ce que j'utilise toujours. Elle vous permet d'utiliser les méthodes d'aide et de tenir compte du comportement d'ASP.NET MVC.

8 votes

Ou dans le cas de non vérifié : bool bChecked = form[key].Equals("false") ; Faire un .Contains("false") échoue car la valeur vraie est "true,false".

54voto

Simon_Weaver Points 31141

Au cas où vous vous demanderiez 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 <input type="hidden".../> pour les cases à cocher. Cela permet de résoudre les scénarios où cases à cocher non cochées ne sont pas envoyées dans la la demande. L'envoi d'une entrée cachée permet de savoir que la case à cocher était présente sur la page lorsque la demande a été soumise.

Je suppose que, dans les coulisses, ils ont besoin de le savoir pour lier les paramètres aux méthodes d'action du contrôleur. Vous pourriez alors avoir un booléen à trois états, je suppose (lié à un paramètre bool nullable). Je ne l'ai pas essayé mais j'espère que c'est ce qu'ils ont fait.

4 votes

Oui, c'est pratique dans les scénarios où vous avez des grilles paginées, etc. et vous voulez désélectionner un élément qui a été précédemment sélectionné dans un objet de gestion.

49voto

Simon_Weaver Points 31141

Vous devez également utiliser <label for="checkbox1">Checkbox 1</label> car les gens peuvent alors cliquer sur le texte de l'étiquette ainsi que sur la case à cocher elle-même. Elle est également plus facile à styliser et, au moins dans IE, elle sera mise en évidence lorsque vous naviguerez dans les contrôles de la page.

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

Il ne s'agit pas d'un simple "oh, je pourrais le faire". Il s'agit d'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.

25voto

mmacaulay Points 2048

Voilà ce que j'ai fait.

Voir :

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

Contrôleur :

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

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

J'ai trouvé que les méthodes d'aide de Html.* n'étaient pas si utiles dans certains cas, et que j'étais mieux de le faire en HTML. Ceci étant l'un d'entre eux, l'autre qui me vient à l'esprit est celui des boutons radio.

Edit : ceci est sur la Preview 5, évidemment YMMV entre les versions.

1 votes

Je veux juste ajouter un autre exemple : Object.Property = !String.IsNullOrEmpty(Request.Form["NAME"]) ;

0 votes

Si elle n'est pas cochée, elle passe en exception

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X