Bind multiple radiobuttons to individual booleans

一笑奈何 提交于 2020-02-02 05:17:07

问题


Background

I have a model containing three bools

public class PageDataModel
{
    public bool setting1 { get; set; }
    public bool setting2 { get; set; }
    public bool setting3 { get; set; }
}

If one value is true, the others must be false.

In my view, I am displaying three radio buttons:

The Razor code for my view:

<div class="row">
        <div class="radio">
            @if (Model.Setting1)
            {
                @Html.RadioButtonFor(m => m.Setting1,  "Setting1", new { Checked = "checked", Name = "Group"})
            }
            else
            {
                @Html.RadioButtonFor(m => m.Setting1, "Setting1", new { Name = "Group"})
            }

            @Html.Label("Setting1")
        </div>
        <div class="radio">
            @if (Model.Setting2)
            {
                @Html.RadioButtonFor(m => m.Setting2, "Setting2", new { Checked = "checked", Name = "Group" })
            }
            else
            {
                @Html.RadioButtonFor(m => m.Setting2, "Setting2", new { Name = "Group"})
            }
            @Html.Label("Setting2")
        </div>
        <div class="radio">
            @if (Model.Setting3)
            {
                @Html.RadioButtonFor(m => m.Setting3, "Setting3", new { Checked = "checked", Name = "Group" })
            }
            else
            {
                @Html.RadioButtonFor(m => m.Setting3, "Setting3", new { Name = "Group"})
            }
            @Html.Label("Setting3")
        </div>
        <button type="submit" class="btn btn-default">Save</button>
    </div>

In my controller, I am returning a model with setting1 set to true:

var model = new PageDataModel
        {
            Setting1 = true,
            Setting2 = false,
            Setting3 = false
        };
        return View(model);

This works correctly, the page is loaded with the 'setting 1' radio button checked.

The problem

When I submit the form, the posted model contains all false values, regardless of which radio button was checked.

I've tried changing the value from "setting1" to true/false, but that had no impact on the returned data.

I'm fairly sure I'm not setting up the binding properly, but I'm not sure where I'm going wrong.

All other examples I have found are binding two radio buttons to one bool value (for example, a yes/no pair of radio buttons bound to one bool). I can change the code to use one int property, but I'd like to solve this using bools.

What am I doing wrong? Am I misusing radio buttons here?


回答1:


Technically, this would work fine as long as you have the value set to true. For example:

@Html.RadioButtonFor(m => m.setting1, true)

With that, if the radio is selected, it will post true.

However, the insurmountable problem here is that this is not how radios are designed to function. A radio is part of a group, determined by the value of the name attribute. This causes selecting one radio to deselect all radios with the same name attribute. Using RadioButtonFor, though, will give each radio a different name, based on the property name. In other words, you'd end up with:

<input type="radio" id="setting1" name="setting1" value="true" />
<input type="radio" id="setting2" name="setting2" value="true" />
<input type="radio" id="setting3" name="setting3" value="true" />

Each radio, then, would be part of a different group, consisting of only one radio each (meaning each will be selected by default). You could override the name attribute, but then the posted value would no longer bind to the actual property. For example, if you had:

<input type="radio" id="setting1" name="setting" value="true" />
<input type="radio" id="setting2" name="setting" value="true" />
<input type="radio" id="setting3" name="setting" value="true" />

Such that they're all now part of the same radio group, the value would be posted to setting and it would always be true.

Long and short, there's just no way to make this work like this. What you can do is proxy the value using another property.

public class PageDataModel
{
    public bool setting1 { get; set; }
    public bool setting2 { get; set; }
    public bool setting3 { get; set; }

    public string SelectedSetting
    {
        get
        {
            if (setting1) return "setting1";
            if (setting2) return "setting2";
            if (setting3) return "setting3";
            return null; // or you can set a default here
        }
        set
        {
            switch (value)
            {
                case "setting1":
                    setting1 = true;
                    break;
                case "setting2":
                    setting2 = true;
                    break;
                case "setting3":
                    setting3 = true;
                    break;
            }
        }
    }
}

Then, in your view:

<div class="radio">
    <label>
        @Html.RadioButtonFor(m => m.SelectedSetting, "setting1")
        @Html.DisplayNameFor(m => m.setting1)
    </label>
</div>
<div class="radio">
    <label>
        @Html.RadioButtonFor(m => m.SelectedSetting, "setting2")
        @Html.DisplayNameFor(m => m.setting2)
    </label>
</div>
<div class="radio">
    <label>
        @Html.RadioButtonFor(m => m.SelectedSetting, "setting3")
        @Html.DisplayNameFor(m => m.setting3)
    </label>
</div>

Now, the radios will all be grouped as "SelectedSetting" and will post to the SelectedSetting property. The custom getter and setter on that propery ensures that the proper boolean values will be set on the actual settingX properties.



来源:https://stackoverflow.com/questions/36177782/bind-multiple-radiobuttons-to-individual-booleans

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!