web-dev-qa-db-ja.com

Asp:net MVC 3:@ Html.Editorテンプレート内のモデルのサブコレクションについては?

モデルのサブコレクションを編集するのに長い間立ち往生していて、モデルのコレクションがnullになりました。

私はついに解決策を見つけましたが、少し汚れています:

最初に私のテストデータ:

モデルオブジェクト

    public class ContainerObject
    {
        public String Title { get; set; }
        public List<ContainedObject> ObjectList { get; set; }
    }

サブコレクションオブジェクト

public class ContainedObject
{
    public int Id { get; set; }
    public String Text { get; set; }
    public Boolean IsSelected { get; set; }
}

オブジェクトを生成するコントローラーメソッド

    public ActionResult TestForm()
    {
        return View(new ContainerObject()
        {
            Title = "This is a sample title",
            ObjectList = new List<ContainedObject>()
                {
                    new ContainedObject(){Id=1, IsSelected = true, Text="ObjectOne"},
                    new ContainedObject(){Id=2, IsSelected = false, Text="ObjectTwo"},
                    new ContainedObject(){Id=3, IsSelected = true, Text="ObjectThree"},
                    new ContainedObject(){Id=4, IsSelected = false, Text="ObjectFour"},
                }
        });
    }

編集されたオブジェクトを受け取るコントローラー

    [HttpPost]
    public ActionResult TestFormResult(ContainerObject filledObject)
    {
        return View();
    }

ビュー

@model WebTestApplication.Models.ContainerObject

@{
    ViewBag.Title = "TestForm";
}
@using (Html.BeginForm("TestFormResult","Home", FormMethod.Post)){
    @Html.EditorFor(x => x.Title)
    Html.RenderPartial("ContainedObject", Model.ObjectList);
    <input type="submit"  value="Submit"/>
}

部分ビュー(ContainedObject.cshtml)

@model IEnumerable<WebTestApplication.Models.ContainedObject>
@{
    ViewBag.Title = "ContainedObject";
    int i = 0;
}
@foreach (WebTestApplication.Models.ContainedObject currentObject in Model)
{ 
    <br />
    @Html.Label(currentObject.Text);
    @Html.CheckBox("ObjectList[" + i + "].IsSelected", currentObject.IsSelected);                                                                                                     
    @Html.Hidden("ObjectList[" + i + "].Id", currentObject.Id);                                                                                                
    @Html.Hidden("ObjectList[" + i + "].Text", currentObject.Text);
    i++;
}

これは実際には機能していますが、問題が1つあります。

  • 自分で名前を生成し、コンテナオブジェクトのプロパティを指定する必要があります

ビューでHtml.EditorForの代わりにHtml.RenderPartialを使用しようとしましたが、問題は、「ObjectList。[0] .Id」という名前が生成されることです(プロパティ名とアクセサーの間に。が追加されています)。 )。

また、部分ビューで@ Html.EditorForのみを使用しようとしましたが、オブジェクトの名前で変数が作成されます。

テンプレートを使用しない場合は、次のように機能します。

    @model WebTestApplication.Models.ContainerObject

@{
    ViewBag.Title = "TestForm";
}
@using (Html.BeginForm("TestFormResult", "Home", FormMethod.Post))
{
    @Html.EditorFor(x => x.Title)
    for (int i = 0; i < Model.ObjectList.Count; i++)
    {
        <br />
        @Html.Label(Model.ObjectList[i].Text);
        @Html.CheckBoxFor(m => Model.ObjectList[i].IsSelected);
        @Html.HiddenFor(m => Model.ObjectList[i].Id);
        @Html.HiddenFor(m => Model.ObjectList[i].Text);
    }

    <br /><input type="submit"  value="Submit"/>
}

これは単純なテンプレートですが、実際の場合、はるかに多くのデータがあり、これは何度も再利用されます。それで、私の最良の選択肢は何ですか?

21
J4N

EditorTemplateを導入することで、コードを簡略化できます。方法は次のとおりです。

  • RenderPartialをEditorForに置き換えたことを除いて、メインビューはほとんど同じです。

TestForm.cshtml

@model WebTestApplication.Models.ContainerObject

@{
    ViewBag.Title = "TestForm";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@using (Html.BeginForm("TestFormResult", "Home", FormMethod.Post)) {
    @Html.EditorFor(m => m.Title)
    @Html.EditorFor(m => m.ObjectList);

    <input type="submit" value="Submit" />
}
  • 次に、Views/Homeの下にEditorTemplatesという名前のフォルダーを作成します(コントローラーを想定)家にいる):

enter image description here

  • ContainedObjectの次のテンプレートを追加します。

ContainedObject.cshtml

@model WebTestApplication.Models.ContainedObject

<p>
    @Html.DisplayFor(m => m.Text)
    @Html.CheckBoxFor(m => m.IsSelected)
    @Html.HiddenFor(m => m.Id)
    @Html.HiddenFor(m => m.Text)
</p>

エディターは、各オブジェクトのビューをレンダリングするオブジェクトのリストを自動的に繰り返します。それが役に立てば幸い。

38
Denis Ivin

他に関連するものを探しているときにこのスレッドを見つけました。デニスは正解ですが、他の誰かがこれに遭遇した場合に備えて、構文を追加すると思いました。

「SomeTemplate.cshtml」という名前のエディターテンプレートがある場合は、ビューで次のようにアイテムのリストに使用できます。

@for (var i = 0; i < Model.ObjectList.Count(); i++)
{
    @Html.EditorFor(m => m.ObjectList[i], "SomeTemplate")
}

次に、エディターテンプレートで:

@model WebTestApplication.Models.ContainedObject

<br />
@Html.Label(Model.Text);
@Html.CheckBoxFor(m => m.IsSelected);
@Html.HiddenFor(m => m.Id);
@Html.HiddenFor(m => m.Text);
7
Tom Gerken