将多个单选按钮绑定到单个布尔值

Jay*_*Jay 4 c# asp.net-mvc razor

背景

我有一个包含三个布尔值的模型

public class PageDataModel
{
    public bool setting1 { get; set; }
    public bool setting2 { get; set; }
    public bool setting3 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

如果一个值是true,则其他值必须是false。

在我看来,我正在显示三个单选按钮:

在此处输入图片说明

我认为的剃刀代码:

<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>
Run Code Online (Sandbox Code Playgroud)

在我的控制器中,我将返回一个将setting1设置为true的模型:

var model = new PageDataModel
        {
            Setting1 = true,
            Setting2 = false,
            Setting3 = false
        };
        return View(model);
Run Code Online (Sandbox Code Playgroud)

这可以正常工作,页面已选中“设置1”单选按钮。

问题

当我提交表单时,无论选中哪个单选按钮,发布的模型都包含所有错误值。

我尝试将值从“ setting1”更改为true / false,但这对返回的数据没有影响。

我相当确定我没有正确设置绑定,但是我不确定哪里出错了。

我发现的所有其他示例都将两个单选按钮绑定到一个bool值(例如,将一对单选按钮绑定到一个bool)。我可以更改代码以使用一个int属性,但我想使用布尔值解决此问题。

我究竟做错了什么?我在这里滥用单选按钮吗?

Chr*_*att 5

从技术上讲,只要您将值设置为,就可以正常工作true。例如:

@Html.RadioButtonFor(m => m.setting1, true)
Run Code Online (Sandbox Code Playgroud)

这样,如果选择了广播,它将发布true

但是,这里无法解决的问题是,这不是无线电设计的功能。无线电是组的一部分,由name属性的值确定。这导致选择一个无线电以取消选择具有相同name属性的所有无线电。RadioButtonFor但是,根据属性名称,使用会为每个无线电赋予不同的名称。换句话说,您将得到:

<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" />
Run Code Online (Sandbox Code Playgroud)

这样,每个无线电将属于不同组的一部分,每个无线电仅由一个无线电组成(这意味着默认情况下将选择每个无线电)。您可以覆盖name属性,但是发布的值将不再绑定到实际属性。例如,如果您有:

<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" />
Run Code Online (Sandbox Code Playgroud)

这样,它们现在都属于同一个无线电组,则该值将被发布到setting并且始终为真。

总而言之,根本没有办法像这样进行这项工作。您可以做的是使用另一个属性代理该值。

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;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,在您看来:

<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>
Run Code Online (Sandbox Code Playgroud)

现在,所有收音机将被分组为“ SelectedSetting”,并将发布到该SelectedSetting属性。该settingX属性的自定义getter和setter确保在实际属性上设置正确的布尔值。