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下拉列表复杂的父模型

你在这里有很多错误,其中一些你还没有注意到。但你会的。

第一个是永远不要将下拉列表的集合命名为与所选值相同。MVC以一些不明显的方式使用ViewBagViewState,如果你这样做,你会遇到很多麻烦。将您的项目列表更改为StateProvinceListCountyList, PhoneTypeListAddressTypeList

第二件事是,您将无法正确地将值发回控制器,因为您正在使用部分视图来呈现集合的子项,并将该项作为模型传递给视图。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)