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

我有一个表格:

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

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

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

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

【问题讨论】:

    标签: c# asp.net-mvc razor radio-button


    【解决方案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("{0}{1} {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 项目附带的库存标准,因此对“道具”的更改感到抱歉。干杯。
      猜你喜欢
      • 2011-08-24
      • 2011-02-16
      • 2011-07-24
      • 2021-10-23
      • 1970-01-01
      • 1970-01-01
      • 2015-09-20
      • 2016-11-01
      • 2015-03-19
      相关资源
      最近更新 更多