0

髪を引きちぎり終わったので、助けを求めています。リストのリストを表示する短い再帰 HTML ヘルパーを作成しました。編集内容をコントローラーに戻したい。子の子は null を返し続けます。再帰を削除して、「for ループ」の 2 番目のレイヤーを強制的に通過させると、うまくいくようです。どんな手掛かり?私は RAZOR にタオルを投げ入れようとしていて、Jquery でこれらすべてを行うことを学ぶだけです...

私のコードに基づいて、モデルがポストバックされたときに問題がここに存在します(これは、投稿 ActionResult メソッドのコメントに表示されます):

Node.Name は問題ありません

Node.Children[0].Name は問題ありません

Node.Children[1].Name は問題ありません

Node.Children[1].Children = null (ここに問題があります!)

コントローラーコード

       public ActionResult Y()
    {
        Node driverTree = new Node() { Name="Level1", Children = new List<Node>() };
        driverTree.Children.Add(new Node() { Children = null, Name = "Level2A" });
        driverTree.Children.Add(new Node() {Name ="Level2B", Children = new List<Node> {new Node{Name="Level3A", Children=null},
                                                                                 new Node{Name="Level3B", Children=null}}
        });
        return View(driverTree);
    }
    [HttpPost]
    public ActionResult Y(Node Node)
    {
        //Keeps returning:
            // Node.Name is ok
            // Node.Children[0].Name is ok
            // Node.Children[1].Name is ok
            // Node.Children[1].Children = null (HERE LIES THE PROBLEM!)
        int x = 5; // 
        return View();
    }
}

public class Node
{
    public string Name { get; set; }
    public List<Node> Children { get; set; }
    public bool IsChecked { get; set; }
}

コードを表示

@model JqueryUITests.Controllers.Node
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
<script src="../../Scripts/jquery-ui-1.10.3.min.js" type="text/javascript"></script>
<script src="../../Scripts/jquery-ui.unobtrusive-2.1.0.min.js" type="text/javascript"></script>
}

@helper ShowTree(List<JqueryUITests.Controllers.Node> children)
{
<ul>
    @for (int i = 0; i < children.Count;i++ )
    {
        <li>
            @Html.EditorFor(x => children[i].Name)
            @if (children[i].Children != null)
            {
                @ShowTree(children[i].Children)
            }
        </li>
    }
</ul>
}
@using (Html.BeginForm())
{
<ul id="tree">
    <li>
        @Html.EditorFor(x=>Model.Name)
        @ShowTree(Model.Children)
    </li>
</ul>
<p>
    <input type="submit" value="Create" />
</p>

}

HTMLコード

<form action="/X/Y" method="post">    <ul id="tree">
    <li>
        <input class="text-box single-line" id="Name" name="Name" type="text" value="Level1" />
            <ul>
        <li>
            <input class="text-box single-line" id="children_0__Name" name="children[0].Name" type="text" value="Level2A" />
        </li>
        <li>
            <input class="text-box single-line" id="children_1__Name" name="children[1].Name" type="text" value="Level2B" />
<ul>
        <li>
            <input class="text-box single-line" id="children_0__Name" name="children[0].Name" type="text" value="Level3A" />
        </li>
        <li>
            <input class="text-box single-line" id="children_1__Name" name="children[1].Name" type="text" value="Level3B" />
        </li>
</ul>
        </li>
</ul>

    </li>
</ul>
<p>
    <input type="submit" value="Create" />
</p>

4

3 に答える 3

2

リストは各ノードのアイテムをレンダリングしていますが、各ノードの名前属性を適切にレンダリングしていません。

Razor は、入力がポストバックされてモデルが再作成されるときに、name 属性を使用して配列を作成することでリストを処理します。例えば

List<Foo> AllMyFoos { new Foo { Id = 1 }, new Foo { Id = 2 }, new Foo { Id = 3 }}

次のように(上記の例のように)レンダリングされます。

<input type="text" name="AllMyFoos[0].Id" />
<input type="text" name="AllMyFoos[1].Id" />
<input type="text" name="AllMyFoos[2].Id" />

内部では、Razor と MVC のモデル バインディングが Foo オブジェクトのリストを再作成し、それをコントローラー メソッドに渡します。

再帰メソッドの問題は、子ノードのリストでそれを呼び出すと、各子ノードのインデックスがレンダリングされ、それを別のノードの子として定義している情報が失われることです。

それは理にかなっていますか?

この SO の質問を見て、コレクション型の表示テンプレートに関する回答を読んでください。目的を達成するためのより良い方法です。

SO 表示テンプレートの回答

于 2013-07-01T21:00:48.527 に答える
1

問題は明らかです:

@Html.EditorFor(x => children[i].Name)

通常x、 はモデルを表し、プロパティは format ですx.children[i].Name。次のレベルは x.children[i].children[j].Name です。その式からフィールドEditorForの ID と名前を導き出します。<input />あなたの場合、式は alwayschildren[i].Nameであるため、 root に対する id/name のマッピングが中断されますModel

あなたが望むように再帰レンダリングを行う良い方法があるかどうかはわかりません。おそらく非ラムダ バージョンを使用してHtml.Editor(string expression)、式を文字列として構築し、コード内のネスト レベルに注意します (例: @Html.Editor("Children[1].Children[2].Name"))。

あなたは適切な価値を生み出す責任があります"Children[1].Children[2].Name"

于 2013-07-02T18:00:31.400 に答える
0

表示テンプレートに関する dav83 の発言の拡張。このように見えるはずです。

ファイル

Views\DisplayTemplates\Node.cshtml

@model JqueryUITests.Controllers.Node

<li>
    @Html.EditorFor(x => x.Name)
    @if (Model.Children != null)
    {
        <ul>
            @Html.Editor(x => x.Children)
        </ul>
    }
</li>

今、あなたの見解に入れます。

@model JqueryUITests.Controllers.Node
@section Scripts 
{
    @Scripts.Render("~/bundles/jqueryval")
    <script src="../../Scripts/jquery-ui-1.10.3.min.js" type="text/javascript"></script>
    <script src="../../Scripts/jquery-ui.unobtrusive-2.1.0.min.js" type="text/javascript"></script>
}

@using (Html.BeginForm())
{
    <ul id="tree">
        @Html.EditorForModel()
    </ul>
    <p>
        <input type="submit" value="Create" />
    </p>
}

MVC は、モデルの Node DisplayTemplate を使用して HTML をレンダリングします。さらに、 を呼び出すと@Html.EditorFor(x => x.Children)、表示テンプレートを使用してコレクション内の各アイテムがレンダリングされます。これは、ツリー全体を構築するための再帰を取得する場所です。

さらに、ツリー内の場所を追跡し、HTML 要素に正しく名前を付けて、期待どおりにツリーを投稿できるようにします。

于 2013-07-02T18:23:33.410 に答える