MVC下拉列表复杂的父模型
本文关键字:模型 复杂 下拉列表 MVC | 更新日期: 2023-09-27 18:07:33
我想我在这里错过了一个简单的原则,有人会很快指出来。我实际上有一个Person对象,它包含一些基本属性,然后是几个Lists<>用于电话和地址。电话和地址各有一个类型(家庭/工作/等)。地址也有一个州和县。
当我执行管理操作时,我正在为CountyId, StateProvinceID等设置ViewBag,但是当我有第二个地址或电话时,这些下拉框似乎没有正确的选择值。
我敢肯定这是我做错了什么可悲的基本…
解决…
我知道我缺少一些基本的东西,答案是简单地为Address和Phone对象创建自定义视图模型。这些新的视图模型可以包含这些选择列表中的每个列表…
模型示例
public CustomerModel()
{
IsActive = true;
if (Phones == null)
{
Phones = new List<Phone>();
}
if (Addresses == null)
{
Addresses = new List<Address>();
}
}
public Guid Id { get; set; }
public Guid OrganizationId { get; set; }
[Required]
public String FirstName { get; set; }
public String MiddleName { get; set; }
[Required]
public String LastName { get; set; }
[RegularExpression(".+''@.+''..+", ErrorMessage = "Please enter a valid email address.")]
public String EmailAddress { get; set; }
[DataType(DataType.Date)]
public DateTime? DateOfBirth { get; set; }
public List<Phone> Phones { get; set; }
public List<Address> Addresses { get; set; }
}
父视图示例
<tbody id="tblAddressRows">
@foreach (var address in Model.Addresses)
{
Html.RenderPartial("_AddressRow", address);
}
</tbody>
局部视图示例
<td>
@Html.HiddenFor(a => a.Id)
@Html.DropDownList("AddressTypeId", ViewData["AddressTypeId"] as SelectList)
</td>
<td class="AddressLines">
@Html.EditorFor(a => a.AddressLine1)
@Html.EditorFor(a => a.AddressLine2)
</td>
<td>
@Html.EditorFor(a => a.City)
</td>
<td>
@Html.DropDownListFor(m => m.StateProvinceId, ViewData["StateProvinceId"] as SelectList, new {@class = "State"})
</td>
<td>
@Html.EditorFor(a => a.PostalCode, new {@class = "ZipCode"})
</td>
<td>
@Html.DropDownList("CountyId", ViewData["CountyId"] as SelectList, new {@class = "County"})
</td>
控制器示例
//
// GET: /Customer/Manage/5
public ActionResult Manage(Guid id)
{
CustomerModel customer = DataService.GetCustomer(id, HttpContext.User.Identity.Name);
if (customer == null)
{
return HttpNotFound();
}
ViewBag.AddressTypeId = new SelectList(DataService.GetOrganizationAddressTypes(HttpContext.User.Identity.Name), "Id", "Name");
ViewBag.PhoneTypeId = new SelectList(DataService.GetOrganizationPhoneTypes(HttpContext.User.Identity.Name), "Id", "Name");
ViewBag.StateProvinceId = new SelectList(DataService.GetStates(), "Id", "Name");
ViewBag.CountyId = new SelectList(DataService.GetCounties(0), "Id", "Name");
return View(customer);
}
你在这里有很多错误,其中一些你还没有注意到。但你会的。
第一个是永远不要将下拉列表的集合命名为与所选值相同。MVC以一些不明显的方式使用ViewBag
和ViewState
,如果你这样做,你会遇到很多麻烦。将您的项目列表更改为StateProvinceList
和CountyList
, PhoneTypeList
和AddressTypeList
。
第二件事是,您将无法正确地将值发回控制器,因为您正在使用部分视图来呈现集合的子项,并将该项作为模型传递给视图。MVC将基于模型的对象作为根呈现,并创建名称,假设是这种情况。如果你将这些项提交给一个接受父类的操作方法,那么模型绑定器将无法正确地绑定部分呈现的值(因为MVC将它们呈现为子模型,而不是子模型的集合)。
您应该使用EditorTemplate,它将做几件事。首先,EditorTemplate将自动遍历任何集合,其次,它将呈现表单控件的名称,并使用考虑到父类的适当名称。
在这里阅读更多关于EditorTemplates的信息:
http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html 除了:
为什么你使用一个下拉列表为与州省,而县和地址下拉列表?如果可以,请始终使用强类型版本,这有助于防止表单项命名错误。
另一件事,为什么在构造函数中使用if块?根据定义,构造函数只在构造对象时被调用,因此属性将始终为null(好吧,有人可以从您的类派生并在子类构造函数中设置这些属性,但如果是您的代码,您将知道)
尝试将部分视图放在shared/editortemplates文件夹中并使用html。编辑器(model => model.address)