Pour la réponse courte, vous devez faire trois choses :
- Retirer le
new { Checked = "checked" }
à partir du deuxième bouton radio. Cette valeur cochée codée en dur annulera toute la magie.
- Lorsque vous renvoyez votre ViewResult à partir de l'action du contrôleur, donnez-lui une instance de votre classe de modèle où TermsAndConditions est false. Cela fournira la valeur false par défaut dont vous avez besoin pour que le bouton radio false soit présélectionné pour vous.
- Utilice
true
y false
comme valeurs pour vos boutons radio au lieu de "True"
y "False"
. Ceci est dû au fait que votre propriété est de type bool
. Strictement parlant, vous avez choisi par coïncidence les représentations correctes des chaînes de caractères pour true
y false
mais le paramètre de valeur pour la méthode RadioButtonFor est de type object
. Il est préférable de passer le type réel auquel vous voulez comparer plutôt que de le convertir vous-même en chaîne. Plus d'informations à ce sujet ci-dessous.
Voici ce qui se passe en profondeur :
Le framework veut faire tout cela pour vous automatiquement, mais vous avez fait ces deux premières choses incorrectement, ce qui vous oblige à vous battre avec le framework pour obtenir le comportement que vous voulez.
La méthode RadioButtonFor appelle .ToString()
sur la valeur de la propriété que vous avez spécifiée et la compare à la propriété .ToString()
de la valeur que vous avez transmise lors de la création du bouton radio. S'ils sont égaux, il définit en interne isChecked = true
et finit par rendre checked="checked"
dans le HTML. C'est ainsi qu'il décide du bouton radio à vérifier. Il compare simplement la valeur du bouton radio à la valeur de la propriété et vérifie celle qui correspond.
Vous pouvez rendre des boutons radio pour pratiquement n'importe quelle propriété de cette façon et cela fonctionnera comme par magie. Les chaînes de caractères, les ints et même les types d'enum fonctionnent tous ! Tout objet qui possède un ToString
qui renvoie une chaîne représentant de manière unique la valeur de l'objet fonctionnera. Vous devez simplement vous assurer que vous paramétrez la valeur du bouton radio à une valeur que votre propriété pourrait avoir. La façon la plus simple de le faire est de passer la valeur elle-même, et non la représentation en chaîne de la valeur. Laissez le framework la convertir en chaîne pour vous.
(Puisque vous avez passé dans les représentations correctes de la chaîne de caractères de true
y false
alors ces valeurs fonctionneront tant que vous corrigerez vos deux erreurs réelles, mais il est toujours sage de transmettre les valeurs réelles et non leurs chaînes).
Votre première véritable erreur a été de coder en dur Checked = "checked"
pour le bouton radio "Non". Cela annule ce que le framework essaie de faire pour vous et fait en sorte que ce bouton radio soit toujours coché.
Il est évident que vous voulez que le bouton radio "Non" soit présélectionné, mais vous devez le faire d'une manière qui soit compatible avec tout ce qui précède. Vous devez donner à la vue une instance de votre classe modèle où TermsAndConditions est défini à false, et la laisser "lier" cette instance aux boutons radio. Normalement, une action de contrôleur qui répond à la requête GET initiale d'une URL ne donne pas du tout à la vue une instance de la classe de modèle. En général, on se contente de return View();
. Cependant, puisque vous voulez qu'une valeur par défaut soit sélectionnée, vous devez fournir à la vue une instance de votre modèle dont la valeur de TermsAndConditions a été fixée à false.
Voici un code source illustrant tout cela :
Une sorte de classe de compte que vous avez probablement déjà. (Le modèle de votre vue) :
public class Account
{
public bool TermsAndConditions { get; set; }
//other properties here.
}
Quelques méthodes dans votre contrôleur :
//This handles the initial GET request.
public ActionResult CreateAccount()
{
//this default instance will be used to pre-populate the form, making the "No" radio button checked.
var account = new Account
{
TermsAndConditions = false
};
return View( account );
}
//This handles the POST request.
[HttpPost]
public ActionResult CreateAccount( Account account )
{
if ( account.TermsAndConditions )
{
//TODO: Other validation, and create the account.
return RedirectToAction( "Welcome" );
}
else
{
ModelState.AddModelError( "TermsAndConditionsAgreement", "You must agree to the Terms and Conditions." );
return View( account );
}
}
//Something to redirect to.
public ActionResult Welcome()
{
return View();
}
La vue entière :
@model Account
@{
ViewBag.Title = "Create Account";
}
@using ( Html.BeginForm() )
{
<div>
<span>Do you agree to the Terms and Conditions?</span>
<br />
@Html.RadioButtonFor( model => model.TermsAndConditions, true, new { id = "TermsAndConditions_true" } )
<label for="TermsAndConditions_true">Yes</label>
<br />
@Html.RadioButtonFor( model => model.TermsAndConditions, false, new { id = "TermsAndConditions_false" } )
<label for="TermsAndConditions_false">No</label>
<br />
@Html.ValidationMessage( "TermsAndConditionsAgreement" )
</div>
<div>
<input id="CreateAccount" type="submit" name="submit" value="Create Account" />
</div>
}
BONUS : Vous remarquerez que j'ai ajouté une petite fonctionnalité supplémentaire aux boutons radio. Plutôt que d'utiliser du texte brut pour les étiquettes des boutons radio, j'ai utilisé le langage HTML label
avec l'élément for
défini sur les ID de chaque bouton radio. Cela permet aux utilisateurs de cliquer sur l'étiquette pour sélectionner le bouton radio au lieu de devoir cliquer sur le bouton radio lui-même. Il s'agit d'un code HTML standard. Pour que cela fonctionne, j'ai dû définir des ID manuels sur les boutons radio, sinon ils auraient tous deux reçu le même ID, à savoir "TermsAndConditions", ce qui n'aurait pas fonctionné.