При использовании .net MVC RadioButtonFor(), как вы группируетесь, можно сделать только один выбор?

У меня есть тупик, у меня есть строго типизированное представление, которое имеет этот цикл для генерации радиообъектов:

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

Он отлично отображает, но поскольку имена не совпадают, вы можете выбрать более 1 радиообъектива. Как я могу группировать их, поэтому можно выбрать только 1 радиообъект?

Любая помощь будет оценена!

Ответ 1

Первым параметром Html.RadioButtonFor() должно быть имя свойства, которое вы используете, а второй параметр должен быть значением этого конкретного переключателя. Затем они будут иметь одно и то же значение атрибута имени, и помощник выберет данную радиокнопку, если/если она соответствует значению свойства.

Пример:

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

Вот более конкретный пример:

Я сделал быстрый проект MVC с именем "DeleteMeQuestion" (префикс DeleteMe, поэтому я знаю, что могу его удалить позже, когда я забуду об этом).

Я сделал следующую модель:

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

В модели есть простой валидатор диапазона, просто для удовольствия. Затем я сделал следующий контроллер:

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

Наконец, я сделал следующее представление, которое использует модель:

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

Насколько я понимаю ваш контекст, у вас есть вопросы со списком доступных ответов. Каждый ответ будет диктовать следующий вопрос. Надеюсь, это имеет смысл из моей модели и комментариев TODO.

Это дает вам переключатели с одинаковым атрибутом имени, но разные идентификационные атрибуты.

Ответ 2

В моем случае у меня был набор переключателей, которые должны были быть в группе. Я просто включил свойство "Selected" в модель. Затем, в цикле для вывода радиолюбителей, просто выполните...

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

Таким образом, имя будет одинаковым для всех переключателей. Когда форма отправляется, свойство "Выбранное" равно названию категории (или идентификатору или любому другому), и это может быть использовано для обновления привязки на соответствующем радиообъекте, как это...

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

Не лучший способ, но он работает.

Ответ 3

В случаях, когда атрибут имени отличается, проще всего управлять группой радио через JQuery. Когда опция выбрана, используйте JQuery, чтобы отменить другие параметры.