0

我已经把头发扯断了,所以我正在寻求帮助。我构建了一个简短的递归 HTML Helper 来显示列表列表。我想将任何编辑返回给控制器。一个孩子的孩子不断回来为空。当我删除递归并强制通过“for循环”的第二层时,它似乎有效。有什么线索吗?我即将在 RAZOR 上认输,只是学习在 Jquery 中完成所有这些......

根据我的代码,当模型被回发时,问题就出在这里(您将在 post 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>

}

代码

<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 question 并阅读有关集合类型显示模板的答案 - 这是实现您所追求的更好的方法。

SO 显示模板答案

于 2013-07-01T21:00:48.527 回答
1

问题很明确:

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

通常x表示模型,然后属性是格式x.children[i].Name。下一级是 x.children[i].children[j].Name。从该表达式EditorFor派生字段的 id 和名称。<input />在您的情况下,表达式总是children[i].Name,因此它会破坏 id/name 相对于您的 root 的映射Model

我不确定是否有一种像你想要的那样进行递归渲染的好方法。也许使用非 lambda 版本Html.Editor(string expression),您可以在其中将表达式构造为字符串,并注意代码中的嵌套级别(例如:)@Html.Editor("Children[1].Children[2].Name")

您将负责产生适当的价值"Children[1].Children[2].Name"

于 2013-07-02T18:00:31.400 回答
0

扩展 dav83 关于显示模板的评论。它应该看起来像这样。

文件

视图\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 回答