我正在创建一个注册新用户的表单,每个用户都可以拥有多个地址。 (许多地址给一个用户)。我发现这篇文章但对我来说不合适,因为我有一个主要属性是用户,地址必须与之相关。我想创建一些类似的东西,即使在新用户的创建屏幕中添加了许多地址,也不存在这些地址的用户主键相关。
http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/
有人可以举例说明如何更好的方法吗?
这与我的代码非常接近:
public class Person{
public int PersonId { get; set; }
public string Name { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
}
public class Address{
public int AddressId { get; set; }
public string Street { get; set; }
[ScriptIgnore]
public virtual Person Person { get; set; }
}
答案 0 :(得分:2)
正如Klors所说,为地址和人物创建一个视图模型(建议List<AddressVM>
在PersonVM
构造函数中初始化)。在PersonController
[HttpGet]
public ActionResult Create()
{
PersonVM model = new PersonVM();
model.Addresses.Add(new AddressVM()); // add an empty address assuming at least one required
return View(model, "Edit")
}
[HttpGet]
public ActionResult Edit(int ID)
{
PersonVM model = // get from database/repository
// If Address.Count == 0, add new Address
return View(model);
}
[HttpPost]
public ActionResult Edit(PersonVM model)
{
...
在你看来
@model PersonVM
@using (Html.BeginForm("Edit", "Person") {
....
@Html.HiddenFor(m => m.ID)
@Html.TextBoxFor(m => m.Name)
...
@Html.EditorFor(m => m.Addresses) // you may want to create an editor template for AddressVM
<button type="button" id="AddAddress">Add address</button>
EditorFor()
将生成与此类似的HTML(请注意索引器)
<input type="text" name="Address[0].Street" id="Address_0__Street" ..../>
<input type="text" name="Address[0].Suburb" id="Address_0__Suburb" ..../>
要动态添加新地址,您需要使用JavaScript生成类似的HTML,但增加索引器。如果您使用编辑器模板,则可以将Address
控件包装在容器中(例如<div class="address">
),这样可以根据下面的脚本轻松选择
动态添加新地址的脚本
$('#AddAddress').click(function() {
var addresses = $('.address');
// Get the number of existing address
var count = addresses.length;
// Get the first address and clone it
var clone = addresses.first().clone();
// Update the index of the clone
clone.html($(clone).html().replace(/\[0\]/g, '[' + count + ']'));
clone.html($(clone).html().replace(/"_0__"/g, '_' + count + '__'));
// Add to the DOM
addresses.last().after(clone);
}
请注意,这也将克隆第一个地址中的值,因此您可能希望重置部分或全部值,例如(在添加之后)
clone.find('input').val('');
如果您使用的是@Html.ValidationMessageFor()
方法,请注意,除非您解析表单,否则不会在浏览器中验证动态添加的元素。可以在此处找到如何执行此操作的示例:jquery.validate.unobtrusive not working with dynamic injected elements
答案 1 :(得分:1)
像this这样的东西可能更接近你需要的东西。您需要设想复选框是用于输入地址的字段集合。
但是,如果为Person创建包含ViewModel for Address列表的ViewModel,则可以创建强类型编辑器模板并显示与ViewModel相同的模板,如果使用{{{},则会自动获取它们。 1}}和@Html.EditorFor
使得一对多的工作变得更容易。
如果你有这样的文件 -
@Html.DisplayFor
和一个人ViewModel有点像
~/Models/PersonViewModel.cs
~/Models/AddressViewModel.cs
~/Views/Person/Edit.cshtml
~/Views/Shared/DisplayTemplates/AddressViewModel.cshtml
~/Views/Shared/EditorTemplates/AddressViewModel.cshtml
如果您有像
这样的人的编辑视图public class PersonViewModel
{
public int Id { get; set; }
public string Name { get; set; }
...
public List<AddressViewModel> Addresses { get; set; }
}
然后,对于列表中的每个条目,应该为AddressViewModel选择一次编辑器模板。您必须添加一些Ajax以允许创建新的地址,就像您的示例链接一样。只要模板包含AddressViewModel工作的所有字段,那么您的Edit POST控制器应该只接收PersonViewModel作为其参数。
我的示例中缺少一些部分,但您应该能够填写教程中的空白。