141

Does anyone know how to bind a Yes/No radio button to a boolean property of a Strongly Typed Model in ASP.NET MVC.

Model

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

View

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

Thanks

SOLUTION:

Thanks for Brian for the direction but it was the opposite of what he wrote. As so -

<%@  Page Title="blah"  Inherits="MyClass"%>
<dd>
    <%= Html.RadioButton("blah", !Model.blah) %> Yes
    <%= Html.RadioButton("blah", Model.blah) %> No
</dd>
Daniel Imms
  • 47,944
  • 19
  • 150
  • 166
brianstewey
  • 1,792
  • 3
  • 14
  • 14
  • 4
    The "problem" with these solutions (and I'm using the Ben Cull style in my project) is that you can't do labels with them. Both radio button inputs will have the same id and name, so if you you use Html.LabelFor, it will link to the first radio button input in the DOM with that id. Like I said, I'm using this solutions for radio buttons to represent a boolean field, I just wanted people to know that labels will be a bit wonky. – Gromer Dec 19 '11 at 18:44
  • 2
    See Jeff Bobish's answer to see how to fix the label issue elegantly. – René Dec 17 '12 at 14:06

8 Answers8

206

If you're using MVC 3 and Razor you can also use the following:

@Html.RadioButtonFor(model => model.blah, true) Yes
@Html.RadioButtonFor(model => model.blah, false) No
Ben Cull
  • 9,434
  • 7
  • 43
  • 38
77

The second parameter is selected, so use the ! to select the no value when the boolean is false.

<%= Html.RadioButton("blah", !Model.blah) %> Yes 
<%= Html.RadioButton("blah", Model.blah) %> No 
vulcan raven
  • 32,612
  • 11
  • 57
  • 93
Brian Mains
  • 50,520
  • 35
  • 148
  • 257
59

Here is a more complete example using a fieldset for accessibility reasons and specifying the first button as the default. Without a fieldset, what the radio buttons are for as a whole can not be programmatically determined.

Model

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

View

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

You can add a @checked argument to the anonymous object to set the radio button as the default:

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

Note that you can bind to a string by replacing true and false with the string values.

NoWar
  • 36,338
  • 80
  • 323
  • 498
Daniel Imms
  • 47,944
  • 19
  • 150
  • 166
  • You should actually use new { id = Html.Id("married-true") }, reducing potential scope issues of generated id prefixes. – eoleary Jun 19 '15 at 20:14
26

Building slightly off Ben's answer, I added attributes for the ID so I could use labels.

<%: 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" })%>

I hope this helps.

ctc
  • 3,373
  • 1
  • 18
  • 14
23

Adding label tags around the radio buttons using regular HTML will fix the 'labelfor' issue as well:

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

Clicking on the text now selects the appropriate radio button.

Jeff Bobish
  • 596
  • 4
  • 6
8

or MVC 2.0:

<%= Html.RadioButtonFor(model => model.blah, true) %> Yes
<%= Html.RadioButtonFor(model => model.blah, false) %> No
Stafford Williams
  • 9,696
  • 8
  • 50
  • 101
5

If I can throw my hat into the ring, I think there is a cleaner way than the existing answers to reuse the radio button functionality.

Let's say you have the following property in your ViewModel:

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

You can expose that property through a reusable editor template:

First, create the file Views/Shared/EditorTemplates/YesNoRadio.vbhtml

Then add the following code to 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>

You can call the editor for the property by manually specifying the template name in your View:

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

Pros:

  • Get to write HTML in an HTML editor instead of appending strings in code behind.
  • Preserves the DisplayName DataAnnotation
  • Allows clicks on Label to toggle radio button
  • Least possible code to maintain in form (1 line). If something is wrong with the way it is rending, take it up with the template.
KyleMit
  • 30,350
  • 66
  • 462
  • 664
  • This is good, but what about a Third option for Boolean? @Html.RadioButtonFor(Function(Model) Model.IsVerified, True) Yes @Html.RadioButtonFor(Function(Model) Model.IsVerified, False) No @Html.RadioButtonFor(Function(Model) Model.IsVerified, Nothing)) Pending – JoshYates1980 May 11 '16 at 21:39
1

I ended up packaging this into an extension method so (1) I could generate the label and radio at once and (2) so I didn't have to fuss with specifying my own IDs:

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

Usage:

@Html.RadioButtonAndLabelFor(m => m.IsMarried, true, "Yes, I am married")
attack
  • 1,523
  • 12
  • 17