2013-01-24 3 views
8

Tôi đã một mô hình, ApplicantBranchList, được sử dụng như một tài sản trong một mô hình lớn hơn như sau:Làm cách nào để làm cho mẫu trình chỉnh sửa dựa trên danh sách của tôi được ràng buộc đúng cách cho một hành động POST?

[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 có mẫu biên tập của riêng mình, và mẫu trình chỉnh sửa bên trong cho mỗi mục trong 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> 

biên tập này làm cho đúng cách trong giao diện , nhưng trong hành động sau:

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

PreferedBranches.Itemsnull.

Tôi đang làm gì sai?

Trả lời

13

Vấn đề là ASP.NET không thể tìm ra cách liên kết với thuộc tính Model.Items.

Để sửa chữa nó thay thế:

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

với điều này:

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

và thay vì:

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

sử dụng này một:

@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 
} 
+0

Giải pháp này hoạt động khi bạn cần chỉ định tên Mẫu. – MichaelLake

10

Với mẫu MVC và trình chỉnh sửa bạn không cần phải di chuyển qua danh sách và gọi @HTMLEditorFor theo cách thủ công.

Việc làm này:

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

là giống như:

@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 sẽ xử lý lặp qua các mục của bạn và tạo ra các mẫu soạn thảo của bạn một lần mỗi món. Như được lưu ý trong các bình luận mẫu của bạn phải được đặt tên giống như mô hình của bạn. Ngoài ra, định nghĩa mô hình của bạn phải là một biểu diễn số ít của mô hình của bạn, không phải loại IEnumerable. Cuối cùng, như đã lưu ý trong các ý kiến, nếu bạn chỉ định tham số tên mẫu trong cuộc gọi đến @ Html.EditorFor(), bạn sẽ không có lợi ích của việc lặp lại tự động trong bộ sưu tập của bạn. Bạn sẽ cần phải lặp lại theo cách thủ công như được minh họa ở trên.

+0

+1 Hoàn hảo, đơn giản và trực quan. Trên một lưu ý phụ, nếu mẫu trình chỉnh sửa không được đặt tên chính xác như là Lớp mô hình, EditorFor có ghi đè cho phép truyền tên mẫu làm thông số thứ hai. – dizarter

+0

Mặc dù tên mẫu yêu cầu lặp lại thủ công. Bạn không thể sử dụng '@ Html.EditorFor (model => model.Items," TemplateName ")' –