2010-06-24 11 views
61

Éste me ha dejado perplejos, tengo una visión inflexible de tipos que tiene este bucle para generar botones de radio:Al usar .net MVC RadioButtonFor(), ¿cómo se agrupa para que solo se pueda hacer una selección?

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

Se hace muy bien, pero ya que los nombres no son los mismos, se puede seleccionar más de 1 botón de radio. ¿Cómo puedo agruparlos para que solo se pueda seleccionar 1 radiobutton?

¡Cualquier ayuda sería apreciada!

+0

¿Por qué no puede usar 'Html.RadioButton' en su lugar? – Ahmad

+3

Dado que es una vista fuertemente tipada, intento hacer que los datos vuelvan a llenarse en el controlador. ¡Aunque estoy abierto a cualquier sugerencia! –

Respuesta

112

El primer parámetro de Html.RadioButtonFor() debe ser el nombre de propiedad que está utilizando, y el segundo parámetro debe ser el valor de ese botón de opción específico. Entonces tendrán el mismo valor de atributo de nombre y el ayudante seleccionará el botón de opción dado cuando/si coincide con el valor de la propiedad.

Ejemplo:

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

Aquí hay un ejemplo más específico:

Hice un proyecto MVC rápida llamado "DeleteMeQuestion" (DeleteMe prefijo, así que sé que puedo quitarlo más adelante después de Me olvido de eso).

me hizo el siguiente modelo:

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

Hay un sencillo validador rango en el modelo, sólo por diversión. El siguiente, hice la siguiente controlador:

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

Finalmente, hice la siguiente opinión de que hace uso del modelo:

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

Como entiendo su contexto, tiene alguna pregunta con una lista de respuestas disponibles Cada respuesta dictará la siguiente pregunta. Espero que eso tenga sentido en mi modelo y en los comentarios TODO.

Esto le da los botones de opción con el mismo atributo de nombre, pero diferentes atributos de identificación.

+0

Gracias Andrew, pero creo que el campo de nombre está causando el problema, ya que es parte de un bucle. Cuando miro la fuente, muestra AnswerValue [1], AnswerValue [2], etc ... Para poder devolver el resultado de Strongly Typed, este nombramiento es necesario (me gustaría almacenar cada botón de radio en su propio campo). Solo me preguntaba si había alguna forma de hacer una sola funcionalidad de selección. –

+0

¿Puedes compartir una versión delgada de la definición e intención de clase de tu modelo? ¿Su bucle de código tiene la tarea de crear botones de opción para una sola pregunta y todas sus respuestas? ¿Qué propiedad almacena el valor seleccionado? Cosas como esa ayudarían a describir lo que quieres hacer. – a7drew

+0

Todavía estoy en las etapas de desarrollo, así que estoy abierto a las soluciones. Básicamente, queremos presentar preguntas al usuario con resultados de elección múltiple extraídos de un DB. Cada resultado es una pregunta también, con ParentQuestionID como la pregunta principal. Slimmed Model sería de clase pública QuestionAnswer {public int QuesitonID {}, cadena pública QuestionText {}, cadena pública OptionValue {}, cadena pública AnswerValue {}. Pasaría una lista de este modelo. He agregado mi código de bucle a la pregunta original. –

-6

En los casos en que el atributo de nombre es diferente, es más fácil controlar el grupo de radio a través de JQuery. Cuando se selecciona una opción, use JQuery para deseleccionar las otras opciones.

3

En mi caso, tenía una colección de botones de radio que necesitaban estar en un grupo. Acabo de incluir una propiedad 'Seleccionado' en el modelo. A continuación, en el circuito de salida de los botones de radio acaba de hacer ...

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

De esta manera, el nombre es el mismo para todos los botones de radio. Cuando el formulario se ha publicado, la propiedad 'seleccionados' es igual a la categoría del título (o la identificación o lo que sea) y esto se puede utilizar para actualizar la unión en el botón de radio correspondiente, así ...

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

mayo no es la mejor manera, pero funciona.

Cuestiones relacionadas