I have a column in my Model with a NULLABLE boolean value. Now on my View (for editing), I would like to bind that to two radiobuttons: Yes & No. If the value is null, then
The use of multiple Html.RadioButtonFor (m => m.Foo, "true") seems to generate invalid HTML, because it generates controls with identical IDs:
<input **id="Foo"** ... type="radio" value="True">
<input **id="Foo"** ... type="radio" value="False">
I have solved this by making the radio buttons directly in html:
<input type="radio" name="Foo" value="true" id="Foo_True"
<%:Html.WriteCheckedIfTrue(Model.Foo.HasValue && Model.Foo.Value)%>/>
<label for="Foo_True">Yes</label><br/>
<input type="radio" name="Foo" value="false" id="Foo_False"
<%:Html.WriteCheckedIfTrue(Model.Foo.HasValue && !Model.Foo.Value)%>/>
<label for="Foo_False">No</label><br/>
<input type="radio" name="Foo" value="" id="Foo_Null"
<%:Html.WriteCheckedIfTrue(!Model.Foo.HasValue)%>/>
<label for="Foo_Null">Don't Care</label>
make sure to name the radio buttons according to the used viewmodel, eg: Model.Filter.HasImage is named: Filter.HasImage to work with model binding
The "html helper" looks like this:
public static MvcHtmlString WriteCheckedIfTrue(this HtmlHelper htmlHelper,
bool validation)
{
if(validation)
return new MvcHtmlString("checked=\"checked\"");
return new MvcHtmlString(string.Empty);
}
I can across this post late, however here is my solution which handles the setting the values as well. This used an Editor template. You will need to specify the Editor template name. I called mine 'NullableBool'
@model bool?
@{
Layout = null;
IDictionary<string, object> yesAttributes = new Dictionary<string, object>();
IDictionary<string, object> noAttributes = new Dictionary<string, object>();
IDictionary<string, object> naAttributes = new Dictionary<string, object>();
if (Model.HasValue)
{
if (Model.Value)
{
yesAttributes.Add("checked", "checked");
}
else
{
noAttributes.Add("checked", "checked");
}
}
else
{
naAttributes.Add("checked", "checked");
}
}
@Html.RadioButtonFor(m => m, "true", yesAttributes) Yes`
@Html.RadioButtonFor(m => m, "false", noAttributes) No`
@Html.RadioButtonFor(m => m, string.Empty, naAttributes) N/A`
Once you have selected a radio button, there's really no way to unselect it (as a user). I'd suggest that if you really need a three-valued result, that you have three radio buttons -- Yes, No, Don't care.
<%= Html.LabelFor( m => m.Foo ) %>
<%= Html.RadioButtonFor( m => m.Foo, "true" ) %> Yes
<%= Html.RadioButtonFor( m => m.Foo, "false" ) %> No
<%= Html.RadioButtonFor( m => m.Foo, string.Empty ) %> Don't Care
<%= Html.ValidationMessageFor( m => m.Foo ) %>
This is a razor solution to the problem. This is a very old ASP question.
The problem is that you need to set the checked
attribute because the Html.RadioButtonFor
does not check a radio button based on a nullable bool (which appears to be a flaw).
Also by putting the radio buttons inside of the label tag, you can select value by clicking the label.
@model bool?
<label>
<span>n/a</span>
@Html.RadioButtonFor(x => x, "", !Model.HasValue ? new { @checked=true } : null)
</label>
<label>
<span>Yes</span>
@Html.RadioButtonFor(x => x, true, Model.GetValueOrDefault() ? new { @checked = true } : null)
</label>
<label>
<span>No</span>
@Html.RadioButtonFor(x => x, false, Model.HasValue && !Model.Value ? new { @checked = true } : null)
</label>