2012-01-18 20 views
3

MVC3でマルチレベルエディタを作成しようとしています。マルチレベルとは、3つのレベルの階層(親オブジェクト、親の子オブジェクト、子の子オブジェクトの集合)のデータを編集できるようにすることです。私は1つの画面上の階層全体を表示したいので、私は、次のビューモデルを作成Asp.Net MVC3 Razor - 子アイテムのリストがエディタからポストバックされない

namespace MvcApplication1.Models 
{ 
    public class Parent 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
     public Child Child { get; set; } 
    } 

    public class Child 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
     public IEnumerable<SubChild> SubChildren { get; set; }  
    } 

    public class SubChild 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
     private DateTime _date = DateTime.Now; 
     public DateTime Date { get { return _date; } set { this._date = value; } } 
    } 
} 

namespace MvcApplication1.Models.ViewModels 
{ 
    public class ParentViewModel 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
     public Child Child { get; set; } 
     public IEnumerable<SubChild> SubChildren { get { return Child.SubChildren; } set { this.Child.SubChildren = value; } } 
    } 
} 

をし、コントローラがどのように見えるされています

public class ParentController : Controller 
    { 
     public ActionResult MultiLevelEdit(int id) 
     { 
      // Simulate data retrieval 
      Parent parent = new Parent { Id = 2 , Name = "P"}; 
      var child = new Child { Id = 3, Name = "Cild1" }; 
      List<SubChild> children = new List<SubChild>(); 
      children.Add(new SubChild { Id = 3, Name = "S1"}); 
      children.Add(new SubChild { Id = 5, Name = "S 22" }); 
      child.SubChildren = children; 
      parent.Child = child; 
      // Create view model 
      ParentViewModel vm = new ParentViewModel() { Id = parent.Id, Name = parent.Name, Child = parent.Child, SubChildren = parent.Child.SubChildren }; 

      return View(vm); 
     } 

    } 
私のモデルは、おおよそのようになります。

ビューがレンダリングされる:

@model MvcApplication1.Models.ViewModels.ParentViewModel 

@using (Html.BeginForm()) { 
    @Html.ValidationSummary(true) 
    <fieldset> 

    @Html.HiddenFor(model => model.Id) 
    @Html.LabelFor(model => model.Name) 
    @Html.EditorFor(model => model.Name) 
    <hr /> 
    Child 
    <br /> 
    @Html.EditorFor(model => model.Child) 

    <hr /> 
    SubChild 
    <br /> 
    @Html.EditorFor(model => model.SubChildren) 


    <p> 
      <input type="submit" value="Save" /> 
     </p> 
    </fieldset> 
} 

私は共有\ EditorTemplates \ビューで2つのエディタのテンプレートを作成しました:

ChildTemplate.cshtml

@model MvcApplication1.Models.Child 

@{ 
    ViewBag.Title = "Child"; 
} 

<h2>Child</h2> 

@using (Html.BeginForm()) { 
    @Html.ValidationSummary(true) 
    <fieldset> 
     <legend>Child</legend> 

     @Html.HiddenFor(model => model.Id) 

     <div class="editor-label"> 
      @Html.LabelFor(model => model.Name, "Child Name") 
     </div> 
     <div class="editor-field"> 
      @Html.EditorFor(model => model.Name) 
      @Html.ValidationMessageFor(model => model.Name) 
     </div> 
    </fieldset> 
} 

とSubChildTemplate.cshtmlを

@model MvcApplication1.Models.SubChild 

@using (Html.BeginForm()) { 
    @Html.ValidationSummary(true) 
    <fieldset> 
     <legend>SubChild</legend> 

     @Html.HiddenFor(model => model.Id) 

     <div class="editor-label"> 
      @Html.LabelFor(model => model.Name) 
     </div> 
     <div class="editor-field"> 
      @Html.EditorFor(model => model.Name) 
      @Html.ValidationMessageFor(model => model.Name) 
     </div> 

     <div class="editor-label"> 
      @Html.LabelFor(model => model.Date) 
     </div> 
     <div class="editor-field"> 
      @Html.EditorFor(model => model.Date) 
      @Html.ValidationMessageFor(model => model.Date) 
     </div> 
    </fieldset> 
} 

すべては私がしようとただしたときに、正しくレンダリングSubChildrenコレクションがnullの変更を保存します。 I編集方法の2人の署名試み:

[HttpPost] 
public ActionResult MultiLevelEdit(ParentViewModel parentVM) 
{... 

[HttpPost] 
public ActionResult MultiLevelEdit(ParentViewModel parentVM, FormCollection collection) 
{... 

を、それらのいずれにも価値がありません。

誰もがその仕事をするために改善できる点はありますか? ありがとうございます。

答えて

3

テンプレートの名前が正しくありません。次のようになります。

  • ~/Views/Shared/EditorTemplates/Child.cshtml
  • ~/Views/Shared/EditorTemplates/SubChild.cshtml

また、私は非常にあなたのビューモデルのSubChildrenプロパティの目的は表示されません。

あなたはそれを削除し、あなたのメインビューでの可能性:

@model MvcApplication1.Models.ViewModels.ParentViewModel 

@using (Html.BeginForm()) { 
    @Html.ValidationSummary(true) 
    <fieldset> 

    @Html.HiddenFor(model => model.Id) 
    @Html.LabelFor(model => model.Name) 
    @Html.EditorFor(model => model.Name) 
    <hr /> 
    Child 
    <br /> 
    @Html.EditorFor(model => model.Child) 

    <hr /> 
    SubChild 
    <br /> 
    @Html.EditorFor(model => model.Child.SubChildren) 

    <p> 
     <input type="submit" value="Save" /> 
    </p> 
    </fieldset> 
} 

をしかし、あなたの最大の問題は、あなたがHTMLに許可されていない<form>要素を入れ子にしていることです。これは無効なHTMLであり、未定義の動作になります。いくつかの値は投稿されているかもしれませんが、他のものはありません。メインビューにすでにフォームが含まれているので、Html.BeginFormヘルパーをテンプレートの中から削除してください。

+0

ありがとう@ダーリン。その間にテンプレート名を修正しました。私はネストされたフォームの正しさを確信していましたが、提案がなければすぐに取り除くことはできませんでした。今はすべてが正しく表示されます。私はまだ、サーバーにポストバックするときに、モデルに正しくバインドされていないエディタからのいくつかの値にいくつかの問題がありますが、これはSOの別のポストになります。 – Konrad

1

解決策はthis articleを参照してください。魔法はusing(Html.BeginCollectionItem( "..."))ブロックに含まれています。

要するに、デフォルトのモデルバインダーで作業するときは、正しいフィールド名/プレフィックスを使用する必要があります。

+0

@Janさん、ありがとうございます。私はDarinの提案でこの問題を解決しましたが、将来のためのBeginCollectionItem( "...")ヘルパーについて知っておくとよいでしょう。 – Konrad

関連する問題