ASP.NET MVC 单选按钮更新布尔值

Posted

技术标签:

【中文标题】ASP.NET MVC 单选按钮更新布尔值【英文标题】:ASP.NET MVC RadioButton Update Boolean 【发布时间】:2014-01-20 09:26:32 【问题描述】:

我有一个表格:

用户可以在其中添加/更新/删除某人的姓名。名称是PersonViewModel 中的List<NameViewModel> 我对Primary 单选按钮有疑问。我需要将所有名称都放在一个单选按钮组中,并且只允许一个 Primary。

目前,如果我使用html.RadioButtonFor,那么所有按钮都被赋予不同的名称,因此不在同一个组中,并且它们的IsPrimary 布尔属性不会在回发中设置。我可以使用:

<input type="radio" name="radioName"/>

这使分组保持正确,但我不确定如何确保在回发时正确设置 IsPrimary 布尔属性。有人可以给我指导吗?非常感谢。

【问题讨论】:

【参考方案1】:

不需要任何javascript。由于Primary 是所有名称的通用属性,因此将ViewModels 稍微更改如下:

视图模型

public class NameViewModel

    public int Id  get; set; 
    [Required]
    public string FirstName  get; set; 
    public string MiddleName  get; set; 
    [Required]
    public string LastName  get; set; 
    // other properties
    //...


public class PersonViewModel

    public IList<NameViewModel> Names  get; set; 
    [Required]
    public int? Primary  get; set; 
    // other properties
    //...

控制器

public ActionResult Index()

    var viewModel = new PersonViewModel
    
        Names = new List<NameViewModel>
        
            new NameViewModel Id = 1, FirstName = "Stephen", MiddleName = "M", LastName = "Abney",
            new NameViewModel Id = 2, FirstName = "Jim", LastName = "Beam"
        
    ;
    return View(viewModel);


[HttpPost]
public ActionResult Index(PersonViewModel viewModel)

    if (ModelState.IsValid)
    
        NameViewModel primaryName = viewModel.Names.SingleOrDefault(m => m.Id == viewModel.Primary);
        // save the data
    
    return View(viewModel);

查看

@model PersonViewModel
...
@using (Html.BeginForm())

    <div>
        <table>
            <tbody>
                @for (int i = 0; i < Model.Names.Count; i++)
                
                    <tr>
                        <td>
                            @Html.EditorFor(m => m.Names[i].FirstName)
                            @Html.ValidationMessageFor(m => m.Names[i].FirstName)
                        </td>
                        <td>
                            @Html.EditorFor(m => m.Names[i].MiddleName)
                            @Html.ValidationMessageFor(m => m.Names[i].MiddleName)
                        </td>
                        <td>
                            @Html.EditorFor(m => m.Names[i].LastName)
                            @Html.ValidationMessageFor(m => m.Names[i].LastName)
                        </td>
                        <td>
                            @Html.HiddenFor(m => m.Names[i].Id)
                            @Html.RadioButtonFor(m => m.Primary, Model.Names[i].Id, new  id = "Primary_" + i )
                        </td>
                    </tr>
                
            </tbody>
        </table>
    </div>
    <div>
        @Html.ValidationMessageFor(m => m.Primary)
    </div>
    <div>
        <input type="submit" value="Save" />
    </div>

当然我简化了一点,但我想你明白了。

【讨论】:

【参考方案2】:

现在这是一个直截了当的问题。因为您所有的个人NameViewModel 项目都需要保留其唯一名称,以便 MVC 模型绑定器可以正确识别和绑定您的模型。 (我相信你已经猜到了)。

所以现在我们没有单选按钮控件的名称来管理“组”。该名称还用于 HTTP Post 中以标识控件的值。所以现在我们处于第 22 阶段,模型绑定器需要唯一的名称才能在发布时绑定模型,而浏览器需要所有名称都与您所说的相同。

现在您可以使用一些 jQuery voodoo 来执行此操作,例如绑定另一个 data-,然后绑定到具有此名称的每个控件的单击事件。现在我认为这更像是一种 hack 而不是解决方案,但可以做类似的事情。 (是的,这是基本的)

假设这个模型

public class PersonViewModel

    public PersonViewModel()
    
        this.Names = new List<NameViewModel>();
    

    public IList<NameViewModel> Names  get; set; 



public class NameViewModel

    public NameViewModel()
    
        this.IsPrimary = false;
    

    public int ID  get; set; 

    public string FirstName  get; set; 

    public string LastName  get; set; 

    public string MiddleName  get; set; 

    public bool IsPrimary  get; set; 

    public string FullName
    
        get
        
            return string.Format("01 2",
                                this.FirstName,
                                !string.IsNullOrWhiteSpace(this.MiddleName) ? " " + this.MiddleName : "",
                                this.LastName);
        
    

标记

@Html.RadioButtonFor(x => x.Names[i].IsPrimary, true, new  data_group = "myGroup" )

Javascript

$(function () 
        $('input[type="radio"][data-group="myGroup"]').click(function () 
            $('input[type="radio"][data-group="myGroup"]').removeAttr('checked');
            $(this).attr('checked', 'checked')
        );
    );

现在这将为您提供您所描述的结果。现在另一种选择(假设使用上述模型)我们向PrimaryNamePersonViewModel 添加另一个属性,并将其设置为NameViewModel 的ID(或主键)。使您的 PersonViewModel 看起来像。

public class PersonViewModel

    public PersonViewModel()
    
        this.Names = new List<NameViewModel>();
    

    public IList<NameViewModel> Names  get; set; 

    public int PrimaryName  get; set; 

然后你的标记为。

@Html.RadioButton("PrimaryName", name.ID, name.IsPrimary)
@Html.HiddenFor(x => x.Names[i].ID)

现在这也有效,但现在将 PersonViewModel 的“PrimaryName”设置为已检查的 NameViewModel 的 ID。但是,您的 NameViewModel 将丢失 Post 上的 IsPrimary 值,因为我们不会将该值传回。要同时做到这两个,您必须将这两个选项组合起来。

希望这可以帮助您朝着正确的方向前进。任何一种方法(或其他方法)都应该有效。

【讨论】:

很好的答案。感谢您的输入。我一直希望避免使用 jquery,但您的解决方案确实有效(当我将最后一行更改为 $(this).prop('checked', 'checked') 以获得较新的 jquery 版本时)谢谢! 很高兴它成功了。抱歉,我刚刚使用了 VS MVC4 项目附带的库存标准,因此对“道具”的更改感到抱歉。干杯。

以上是关于ASP.NET MVC 单选按钮更新布尔值的主要内容,如果未能解决你的问题,请参考以下文章

Razor 单选按钮不起作用(ASP.NET MVC)

如何使用 asp.net mvc 5 中的单选按钮检索登录详细信息?

如何确定在 C# ASP.NET CORE MVC 5.0 中选择了哪个单选按钮

如何使用 jquery unobtrusive 和 Asp.Net Mvc 验证动态生成的单选按钮组?

如何禁用 ASP.NET MVC 中 HtmlHelper 方法生成的单选按钮和复选框?

mvc 绑定/发布布尔到单选按钮