ASP.NET MVC绑定嵌套列表

时间:2016-05-29 03:02:13

标签: c# asp.net-mvc asp.net-mvc-4 razor asp.net-mvc-5

我正在使用梅尔空间(https://mleeb.wordpress.com/2013/11/23/editing-nested-lists-in-asp-mvc-4/)中建议的解决方案 用于编辑嵌套列表

基本上我的模型如下所示

ProductEditModel

 --> ProductAudioEditModel

    --> ProductAssetResourceEditModel

我让这个工作在下面

 @Html.EditorFor(c => resource.TrackTitle, null, Html.GetHtmlName("TrackTitle"))

在编辑时给出了正确的值。

但是,我无法使用DropDownList,或者我无法在下拉列表中选择已编辑的值。它总是在我的控制器中给我原始值。

 @using (Html.BeginCollectionItem("ProductAssetAudios", out parentIdentifier))
  {
       .....
        @foreach (var resource in Model.ProductAssetResources.OrderBy(a => a.ResourceNumber))
          {
            string childIdentifier = null; 
             @using (Html.BeginChildCollectionItem("ProductAssetResources", parentIdentifier, out childIdentifier))
              {
                  @Html.HiddenFor(model => resource.AssetResourceStatusId, new { Name = Html.GetHtmlName(childIdentifier, "AssetResourceStatusId") })
                  @Html.DropDownListFor(model => resource.AssetResourceStatusId, new SelectList(visibleResourceStatuses, "AssetResourceStatusId", "Name", resource.AssetResourceStatusId),  new { @class = "inherit-title" }) @Html.ValidationMessageFor(model => resource.AssetResourceStatusId)

              }
          }
  }

即使为不同的值选择了下拉列表,AssetResourceStatusId也始终保持原始值。

我希望在编辑嵌套列表时,EditorFor和DropDownListFor应该以相同的方式工作。

被修改

生成的HTML

DropDownListFor

    <select class="inherit-title valid" id="ProductAssetAudios_0df86a5c-0a32-4b0f-97ee-3b3254f743d9__ProductAssetResources_c58ba43c-6081-41d4-88fd-d59799c7374e__resource_AssetResourceStatusId" name="ProductAssetAudios[0df86a5c-0a32-4b0f-97ee-3b3254f743d9].ProductAssetResources[c58ba43c-6081-41d4-88fd-d59799c7374e].resource.AssetResourceStatusId" aria-invalid="false"><option value="3">Extra</option>
    <option selected="selected" value="2">Found</option>
    <option value="8">Ignore</option>
    </select>

HiddenFor

<input name="ProductAssetAudios[b5670a6a-7a1d-4c76-86bc-85a05cd144c1].ProductAssetResources[aa378d38-0fb7-4304-9f24-79d0efcb36b9].AssetResourceStatusId" data-val="true" data-val-number="The field AssetResourceStatusId must be a number." data-val-required="The AssetResourceStatusId field is required." id="ProductAssetAudios_b5670a6a-7a1d-4c76-86bc-85a05cd144c1__ProductAssetResources_aa378d38-0fb7-4304-9f24-79d0efcb36b9__resource_AssetResourceStatusId" type="hidden" value="2">

-Alan -

1 个答案:

答案 0 :(得分:1)

您的模型包含名为ProductAssetAudios的集合属性(typeof ProductAudioEditModel),该集合中的每个对象都包含一个名为ProductAssetResources(typeof ProductAssetResourceEditModel)的集合属性,每个属性都包含这些对象包含名为AssetResourceStatusId的属性。

在C#代码中,如果您在第一个AssetResourceStatusId中获得第一个ProductAssetResourceEditModel的{​​{1}}值,则代码将为

ProductAudioEditModel

删除var id = model.ProductAssetAudios[0].ProductAssetResources[0].AssetResourceStatusId; 前缀,这正是控件的model属性必须如何。 nameBeginCollectionItem()方法的作用是将集合索引器修改为BeginChildCollectionItem(),并为索引器添加隐藏输入,以允许您动态添加和删除集合中的项目。默认情况下,Guid将使用从零开始的连续索引器绑定集合,除非还发布了索引器的值(即添加隐藏输入的原因)。

在您的情况下,隐藏输入的DefaultModelBinder属性是正确的,即使用

name

因为您覆盖@Html.HiddenFor(model => resource.AssetResourceStatusId, new { Name = Html.GetHtmlName(childIdentifier, "AssetResourceStatusId") }) 生成的默认name属性。您只需对HiddenFor()方法执行相同操作,即使用DropDownListFor()设置名称属性。但是,您还需要删除隐藏的输入,因为new { Name = Html.GetHtmlName(childIdentifier, "AssetResourceStatusId") }将仅绑定为属性发布的第一个值。另请注意,您还需要更改DefaultModelBinder

旁注。从评论中看,您似乎不想在视图中添加和删除项目,在这种情况下,请勿使用ValidationMessageFor()BeginCollectionItem()方法。相反,只需使用嵌套的BeginChildCollectionItem()循环或自定义for作为EditorTemplatesProductAudioEditModel的类型。使用ProductAssetResourceEditModel循环的示例是

for

另请参阅this answer以获取使用嵌套for(int i = 0; i < Model.ProductAssetAudios.Count; i++) { @Html.TextBoxFor(m => m.ProductAssetAudios[i].SomeProperty) .... for (int j = 0; j < Model.ProductAssetAudios[i].ProductAssetResources.Count; j++) { @Html.DropDownListFor(m => m.ProductAssetAudios[i].ProductAssetResources[j].AssetResourceStatusId, new SelectList(.....)

的示例