9

次のように、より大きなモデルのプロパティとして使用されるモデルApplicantBranchListがあります。

[Display(Name = "Where would you want to work?")]
public ApplicantBranchList PreferedBranches { get; set; }

ApplicantBranchList

public class ApplicantBranchList : ViewModel
{
    public ApplicantBranchItem HeaderItem { get; set; }
    public ApplicantBranchList()
    {
        HeaderItem = new ApplicantBranchItem();
    }
    public void MapFromEntityList(IEnumerable<ApplicantBranch> applicantBranches)
    {
        var service = new BranchService(DbContext);
        var selectedIds = applicantBranches.Select(b => b.BranchId);
        Items = service.ReadBranches()
                       .Where(i => !i.IsDeleted)
                       .Select(p => new ApplicantBranchItem { BranchName = p.Name, WillWorkAt = selectedIds.Contains(p.Id) });
    }
    public IEnumerable<ApplicantBranchItem> Items { get; set; }
}

ApplicantBranchList独自のエディターテンプレートと、次の各アイテムの内部エディターテンプレートがありますApplicantBranchList

Views / Shared / EditorTemplates / ApplicantBranchList.cshtml:

@model Comair.RI.UI.Models.ApplicantBranchList
<table>
    <tr>
        <th style="display: none;"></th>
        <th>
            @Html.DisplayNameFor(model => model.HeaderItem.BranchName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.HeaderItem.WillWorkAt)
        </th>
    </tr>
    @foreach (var item in Model.Items)
    {
        @Html.EditorFor(m => item)
    }
</table>

Views / Shared / EditorTemplates / ApplicantBranchItem.cshtml:

@model Comair.RI.UI.Models.ApplicantBranchItem
<tr>
    <td style="display: none;">
        @Html.HiddenFor(m => m.BranchId)
    </td>
    <td>
        @Html.DisplayFor(m => m.BranchName)
    </td>
    <td>
        @Html.EditorFor(m => m.WillWorkAt)
    </td>
</tr>

このエディターは、ビューでは適切にレンダリングされますが、ポストアクションでは次のようにレンダリングされます。

public ActionResult Create(ApplicantProfileModel model)
{
    if (ModelState.IsValid)
    {
        var branches = model.PreferedBranches;

PreferedBranches.Itemsですnull

私は何が間違っているのですか?

4

2 に答える 2

16

Model.Items問題は、ASP.NET がプロパティにバインドする方法を理解できないことです。

それを修正するには、次のように置き換えます。

public IEnumerable<ApplicantBranchItem> Items { get; set; }

これとともに:

public List<ApplicantBranchItem> Items { get; set; }

そして代わりに:

@foreach (var item in Model.Items)
{
   @Html.EditorFor(m => item)
}

これを使用してください:

@for (var i = 0; i < Model.Items.Count; i++)
{
   @Html.EditorFor(model => model.Items[i]) // binding works only with items which are accessed by indexer
}
于 2013-01-24T11:26:34.437 に答える
13

MVC とエディター テンプレートを使用すると、手動でリストを移動して @HTMLEditorFor を呼び出す必要はありません。

これを行う:

@Html.EditorFor(model => model.Items)

以下と同じです:

@for (var i = 0; i < Model.Items.Count; i++)
{
   @Html.EditorFor(model => model.Items[i]) // binding works only with items which are accessed by indexer
}

MVC はアイテムの繰り返しを処理し、アイテムごとに 1 回エディター テンプレートを生成します。コメントにあるように、テンプレートにはモデルと同じ名前を付ける必要があります。また、モデル定義は、IEnumerable 型ではなく、モデルの単一表現である必要があります。最後に、コメントに記載されているように、 @Html.EditorFor() への呼び出しでテンプレート名パラメーターを指定すると、コレクションに対する自動反復の利点が得られません。上記のように、手動で繰り返す必要があります。

于 2014-12-18T18:25:08.230 に答える