我有一张表格:
用户可以添加/更新/删除某人的姓名。名称是List<NameViewModel>
PersonViewModel
Primary
我对Html.RadioButtonFor
单选按钮有疑问。我需要所有名称都在radiobutton组中,只允许一个Primary。
目前,如果我使用IsPrimary
,则所有按钮都被赋予不同的名称,因此不在同一组中,并且它们的<input type="radio" name="radioName"/>
布尔属性不会在回发上设置。我可以用:
{{1}}
保持分组正确,但我不确定如何确保在回发时正确设置IsPrimary布尔属性。有人可以给我指导吗?非常感谢你。
答案 0 :(得分:1)
现在这是一个直截了当的问题。由于所有单个NameViewModel
项都需要保留其唯一名称,因此MVC模型绑定器可以正确识别和绑定模型。 (我相信你已经猜到了。)
所以现在我们没有单选按钮控件的名称来管理“组”。该名称也用于HTTP Post中以标识控件的值。所以现在我们处于catch-22模型绑定器需要唯一的名称来绑定模型在post上,并且浏览器需要所有相同的名称才能按照你的说法运行。
现在您可以使用一些jQuery voodoo来执行此操作,例如绑定另一个data-
,然后使用此名称绑定到每个控件的click事件。现在我认为这更像是一个黑客而不是一个解决方案,但可以做类似的事情。 (是的,这是基本的)
假设这个模型
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')
});
});
现在,这将为您提供您所描述的结果。现在是另一种选择(假设使用上面的模型),我们将另一个属性添加到PersonViewModel
PrimaryName
并将其设置为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
将会忽略帖子上的IsPrimary
值。要做到这两点,你必须连接这两个选项的组合。
希望这可以帮助您找到正确的方向。任何一种方法(或其他方法)都应该有用。
答案 1 :(得分:1)
不需要任何JavaScript
。由于Primary
是所有名称的公共属性,因此请更改ViewModels
,如下所示:
的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>
}
当然我简化了一点,但我认为你明白了。