【问题标题】:ASP.NET MVC Binding Nested ListASP.NET MVC 绑定嵌套列表
【发布时间】:2016-09-27 02:35:23
【问题描述】:

我正在使用梅尔空间中建议的解决方案 (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 工作,或者我无法在 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>

隐藏

<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">

-艾伦-

【问题讨论】:

  • 显示由HiddenFor()DropDownListFor() 方法生成的实际html。
  • @StephenMuecke,我已经编辑了我的问题以包含生成的 HTML
  • 使用for-loop 生成html,它应该可以工作
  • 隐藏输入正在创建正确的name 属性,假设ProductEditModel 包含属性IEnumerable&lt;ProductAudioEditModel&gt; ProductAssetAudios 并且ProductAudioEditModel 包含属性IEnumerable&lt;ProductAssetResourceEditModel&gt; ProductAssetAudios。您需要像当前生成隐藏输入一样生成下拉列表,然后删除隐藏输入
  • 我还假设您正在将新项目动态添加到视图中的嵌套集合中,否则您不应该使用它。

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


【解决方案1】:

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

在 C# 代码中,如果您要在第一个 ProductAssetResourceEditModel 中获取第一个 ProductAssetResourceEditModelAssetResourceStatusId 值,那么您的代码将是

var id = model.ProductAssetAudios[0].ProductAssetResources[0].AssetResourceStatusId;

删除model 前缀,这正是控件的name 属性必须如此。 BeginCollectionItem()BeginChildCollectionItem() 方法所做的是将集合索引器修改为 Guid 并为索引器添加隐藏输入,以允许您从集合中动态添加和删除项目。默认情况下,DefaultModelBinder 会将集合与从零开始的连续索引器绑定,除非还发布了索引器的值(即添加隐藏输入的原因)。

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

@Html.HiddenFor(model => resource.AssetResourceStatusId, new { Name = Html.GetHtmlName(childIdentifier, "AssetResourceStatusId") })

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


旁注。从 cmets 看来,您不想在视图中添加和删除项目,在这种情况下,不要使用 BeginCollectionItem()BeginChildCollectionItem() 方法。相反,只需使用嵌套的for 循环或自定义EditorTemplates 用于typeof ProductAudioEditModelProductAssetResourceEditModel。使用for 循环的示例是

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(.....)

另请参阅 this answer 以获取使用嵌套 EditorTemplate 的示例。

【讨论】:

    猜你喜欢
    • 2014-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-24
    • 1970-01-01
    相关资源
    最近更新 更多