web-dev-qa-db-fra.com

Lorsque vous utilisez .net MVC RadioButtonFor (), comment regrouper les éléments afin de ne pouvoir effectuer qu'une seule sélection?

Celui-ci m'a stumped, j'ai une vue fortement typée qui a cette boucle pour générer des radiobuttons:

<% foreach (QuestionAnswer qa in Model.QuestionAnswers)
   { %>
    <%= Html.RadioButtonFor(model => model.QuestionAnswers[(int)qa.QuestionID - 1].AnswerValue, "Checked" ) %>
    <%= Html.Encode(qa.OptionValue) %>
<% } %>

Le rendu est correct, mais comme les noms ne sont pas identiques, vous pouvez sélectionner plus d’un radiobutton. Comment puis-je les regrouper de sorte qu'un seul radiobutton puisse être sélectionné?

Toute aide serait appréciée!

63
Mark Kadlec

Le premier paramètre de Html.RadioButtonFor () doit être le nom de la propriété que vous utilisez, et le deuxième paramètre doit être la valeur de ce bouton radio spécifique. Ensuite, ils auront la même valeur d'attribut name et l'assistant sélectionnera le bouton radio donné lorsque/s'il correspond à la valeur de la propriété.

Exemple:

<div class="editor-field">
    <%= Html.RadioButtonFor(m => m.Gender, "M" ) %> Male
    <%= Html.RadioButtonFor(m => m.Gender, "F" ) %> Female
</div>

Voici un exemple plus spécifique:

J'ai créé un projet MVC rapide appelé "DeleteMeQuestion" (préfixe DeleteMe afin que je sache que je pourrai le supprimer plus tard, une fois que je l'aurais oublié).

J'ai fabriqué le modèle suivant:

namespace DeleteMeQuestion.Models
{
    public class QuizModel
    {
        public int ParentQuestionId { get; set; }
        public int QuestionId { get; set; }
        public string QuestionDisplayText { get; set; }
        public List<Response> Responses { get; set; }

        [Range(1,999, ErrorMessage = "Please choose a response.")]
        public int SelectedResponse { get; set; }
    }

    public class Response
    {
        public int ResponseId { get; set; }
        public int ChildQuestionId { get; set; }
        public string ResponseDisplayText { get; set; }
    }
}

Il existe un simple validateur de plage dans le modèle, juste pour le plaisir. Ensuite, j'ai créé le contrôleur suivant:

namespace DeleteMeQuestion.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
        public ActionResult Index(int? id)
        {
            // TODO: get question to show based on method parameter 
            var model = GetModel(id);
            return View(model);
        }

        [HttpPost]
        public ActionResult Index(int? id, QuizModel model)
        {
            if (!ModelState.IsValid)
            {
                var freshModel = GetModel(id);
                return View(freshModel);
            }

            // TODO: save selected answer in database
            // TODO: get next question based on selected answer (hard coded to 999 for now)

            var nextQuestionId = 999;
            return RedirectToAction("Index", "Home", new {id = nextQuestionId});
        }

        private QuizModel GetModel(int? questionId)
        {
            // just a stub, in lieu of a database

            var model = new QuizModel
            {
                QuestionDisplayText = questionId.HasValue ? "And so on..." : "What is your favorite color?",
                QuestionId = 1,
                Responses = new List<Response>
                                                {
                                                    new Response
                                                        {
                                                            ChildQuestionId = 2,
                                                            ResponseId = 1,
                                                            ResponseDisplayText = "Red"
                                                        },
                                                    new Response
                                                        {
                                                            ChildQuestionId = 3,
                                                            ResponseId = 2,
                                                            ResponseDisplayText = "Blue"
                                                        },
                                                    new Response
                                                        {
                                                            ChildQuestionId = 4,
                                                            ResponseId = 3,
                                                            ResponseDisplayText = "Green"
                                                        },
                                                }
            };

            return model;
        }
    }
}

Enfin, j'ai créé la vue suivante qui utilise le modèle:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<DeleteMeQuestion.Models.QuizModel>" %>

<asp:Content ContentPlaceHolderID="TitleContent" runat="server">
    Home Page
</asp:Content>

<asp:Content ContentPlaceHolderID="MainContent" runat="server">

    <% using (Html.BeginForm()) { %>

        <div>

            <h1><%: Model.QuestionDisplayText %></h1>

            <div>
            <ul>
            <% foreach (var item in Model.Responses) { %>
                <li>
                    <%= Html.RadioButtonFor(m => m.SelectedResponse, item.ResponseId, new {id="Response" + item.ResponseId}) %>
                    <label for="Response<%: item.ResponseId %>"><%: item.ResponseDisplayText %></label>
                </li>
            <% } %>
            </ul>

            <%= Html.ValidationMessageFor(m => m.SelectedResponse) %>

        </div>

        <input type="submit" value="Submit" />

    <% } %>

</asp:Content>

Si je comprends votre contexte, vous avez des questions avec une liste des réponses disponibles. Chaque réponse dictera la question suivante. Espérons que cela soit logique d'après mon modèle et les commentaires de TODO.

Cela vous donne les boutons radio avec le même attribut de nom, mais différents attributs d'ID.

119
a7drew

Dans mon cas, j'avais une collection de boutons radio qui devaient être dans un groupe. Je viens d'inclure une propriété 'Selected' dans le modèle. Ensuite, dans la boucle pour sortir les radiobuttons, faites ...

@Html.RadioButtonFor(m => Model.Selected, Model.Categories[i].Title)

De cette façon, le nom est le même pour tous les boutons radio. Lorsque le formulaire est posté, la propriété 'Selected' est égale au titre de la catégorie (ou id ou autre) et peut être utilisé pour mettre à jour la liaison du radiobutton concerné, comme ceci ...

model.Categories.Find(m => m.Title.Equals(model.Selected)).Selected = true;

Ce n'est peut-être pas la meilleure solution, mais cela fonctionne.

6
simonpkerr