ASP.NET MVC Sí / No Botones de radio con modelo MVC fuertemente vinculado

132

¿Alguien sabe cómo vincular un botón de opción Sí / No a una propiedad booleana de un modelo fuertemente tipado en ASP.NET MVC.

Modelo

public class MyClass
{
     public bool Blah { get; set; }
}

Ver

<%@  Page Title="blah"  Inherits="MyClass"%>
    <dd>
        <%= Html.RadioButton("blah", Model.blah) %> Yes
        <%= Html.RadioButton("blah", Model.blah) %> No
    </dd>

Gracias

SOLUCIÓN:

Gracias por Brian por la dirección, pero fue lo contrario de lo que escribió. Como tal ...

<%@  Page Title="blah"  Inherits="MyClass"%>
<dd>
    <%= Html.RadioButton("blah", !Model.blah) %> Yes
    <%= Html.RadioButton("blah", Model.blah) %> No
</dd>
brianstewey
fuente
44
El "problema" con estas soluciones (y estoy usando el estilo Ben Cull en mi proyecto) es que no puedes hacer etiquetas con ellas. Ambas entradas de botón de radio tendrán la misma identificación y nombre, por lo que si usa Html.LabelFor, se vinculará con la primera entrada de botón de radio en el DOM con esa identificación. Como dije, estoy usando estas soluciones para botones de radio para representar un campo booleano, solo quería que la gente supiera que las etiquetas serán un poco inestables.
Gromer
2
Vea la respuesta de Jeff Bobish para ver cómo solucionar el problema de la etiqueta con elegancia.
René

Respuestas:

74

Se selecciona el segundo parámetro, así que use el! para seleccionar el valor no cuando el booleano es falso.

<%= Html.RadioButton("blah", !Model.blah) %> Yes 
<%= Html.RadioButton("blah", Model.blah) %> No 
Brian Mains
fuente
198

Si usa MVC 3 y Razor, también puede usar lo siguiente:

@Html.RadioButtonFor(model => model.blah, true) Yes
@Html.RadioButtonFor(model => model.blah, false) No
Ben Cull
fuente
56

Aquí hay un ejemplo más completo usando a fieldsetpor razones de accesibilidad y especificando el primer botón como predeterminado. Sin a fieldset, para qué sirven los botones de radio en su conjunto no se puede determinar mediante programación.

Modelo

public class MyModel
{
    public bool IsMarried { get; set; }
}

Ver

<fieldset>
    <legend>Married</legend>

    @Html.RadioButtonFor(e => e.IsMarried, true, new { id = "married-true" })
    @Html.Label("married-true", "Yes")

    @Html.RadioButtonFor(e => e.IsMarried, false, new { id = "married-false" })
    @Html.Label("married-false", "No")
</fieldset>

Puede agregar un @checkedargumento al objeto anónimo para establecer el botón de opción como predeterminado:

new { id = "married-true", @checked = 'checked' }

Tenga en cuenta que puede enlazar a una cadena reemplazando truey falsecon los valores de la cadena.

Daniel Imms
fuente
En realidad, debe usar el nuevo {id = Html.Id ("married-true")}, reduciendo los posibles problemas de alcance de los prefijos de id generados.
Eoleario
26

Basándome un poco en la respuesta de Ben, agregué atributos para la ID para poder usar etiquetas.

<%: Html.Label("isBlahYes", "Yes")%><%= Html.RadioButtonFor(model => model.blah, true, new { @id = "isBlahYes" })%>
<%: Html.Label("isBlahNo", "No")%><%= Html.RadioButtonFor(model => model.blah, false, new { @id = "isBlahNo" })%>

Espero que esto ayude.

ctc
fuente
77
Normalmente la etiqueta está detrás de un botón de radio.
Daniel Imms
66
Poner una etiqueta alrededor de un botón de radio es perfectamente válido.
Scott Baker
23

Agregar etiquetas de etiquetas alrededor de los botones de radio usando HTML normal también solucionará el problema de 'etiqueta para':

<label><%= Html.RadioButton("blah", !Model.blah) %> Yes</label>
<label><%= Html.RadioButton("blah", Model.blah) %> No</label>

Al hacer clic en el texto ahora se selecciona el botón de opción apropiado.

Jeff Bobish
fuente
8

o MVC 2.0:

<%= Html.RadioButtonFor(model => model.blah, true) %> Yes
<%= Html.RadioButtonFor(model => model.blah, false) %> No
Stafford Williams
fuente
5

Si puedo arrojar mi sombrero al ring, creo que hay una forma más limpia que las respuestas existentes para reutilizar la funcionalidad del botón de radio.

Digamos que tiene la siguiente propiedad en su ViewModel :

Public Class ViewModel
    <Display(Name:="Do you like Cats?")>
    Public Property LikesCats As Boolean
End Class

Puede exponer esa propiedad a través de una plantilla de editor reutilizable :

Primero, crea el archivo Views/Shared/EditorTemplates/YesNoRadio.vbhtml

Luego agregue el siguiente código a YesNoRadio.vbhtml :

@ModelType Boolean?

<fieldset>
    <legend>
        @Html.LabelFor(Function(model) model)
    </legend>

    <label>
        @Html.RadioButtonFor(Function(model) model, True) Yes
    </label>
    <label>
        @Html.RadioButtonFor(Function(model) model, False) No
    </label>
</fieldset>

Puede llamar al editor de la propiedad especificando manualmente el nombre de la plantilla en su Vista :

@Html.EditorFor(Function(model) model.LikesCats, "YesNoRadio")

Pros:

  • Escribe HTML en un editor HTML en lugar de agregar cadenas en el código que se encuentra detrás.
  • Conserva la Anotación de datos DisplayName
  • Permite clics en la etiqueta para alternar el botón de opción
  • Mínimo código posible para mantener en forma (1 línea). Si algo está mal con la forma en que está desgarrando, tómalo con la plantilla.
KyleMit
fuente
Esto es bueno, pero ¿qué pasa con una tercera opción para Boolean? @ Html.RadioButtonFor (Function (Model) Model.IsVerified, True) <span> Sí </span> @ Html.RadioButtonFor (Function (Model) Model.IsVerified, False) <span> No </span> @ Html.RadioButtonFor (Función (Modelo) Modelo.Verificado, Nada)) <span> Pendiente </span>
JoshYates1980
1

Terminé empaquetando esto en un método de extensión para que (1) pudiera generar la etiqueta y la radio de una vez y (2) para no tener que preocuparme por especificar mis propios ID:

public static class HtmlHelperExtensions
{
    public static MvcHtmlString RadioButtonAndLabelFor<TModel, TProperty>(this HtmlHelper<TModel> self, Expression<Func<TModel, TProperty>> expression, bool value, string labelText)
    {
        // Retrieve the qualified model identifier
        string name = ExpressionHelper.GetExpressionText(expression);
        string fullName = self.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);

        // Generate the base ID
        TagBuilder tagBuilder = new TagBuilder("input");
        tagBuilder.GenerateId(fullName);
        string idAttr = tagBuilder.Attributes["id"];

        // Create an ID specific to the boolean direction
        idAttr = String.Format("{0}_{1}", idAttr, value);

        // Create the individual HTML elements, using the generated ID
        MvcHtmlString radioButton = self.RadioButtonFor(expression, value, new { id = idAttr });
        MvcHtmlString label = self.Label(idAttr, labelText);

        return new MvcHtmlString(radioButton.ToHtmlString() + label.ToHtmlString());
    }
}

Uso:

@Html.RadioButtonAndLabelFor(m => m.IsMarried, true, "Yes, I am married")
ataque
fuente