无限嵌套在MVC4上

时间:2013-05-27 14:31:07

标签: asp.net-mvc asp.net-mvc-4 razor nested

目标:

具有无限深度的嵌套元素层次结构。

问题:

我有一个A类,其中包含一个B类实例。

B类有一个Comment对象列表。每个评论可能都有一个“孩子”评论列表。

因此,我们有一个树状结构,无限深度嵌套(例如A.B.Comments [1]。评论[0]。评论[5] ....)。

A类编辑查看电话:

@Html.EditorFor(m=>m.B)

B组的编辑模板有(简化):

<table id="B-comments">
    @for (int i = 0; i < Model.Comment.ToList().Count(); i++)
    {
        @Html.EditorFor(m => m.Comment.ToList()[i])
    }
</table>
<a id="addCommentToB" href="#">Add Comment</a>

Comment类的每个Editor Template都包含(简化):

<tr>

   @using (Html.BeginCollectionItem("B.Comment"))
   {
       <td>
           (... STUF ...)    
       </td>

       (...STUF...)

       <td>
           <table class ="commentReplies">
            @for (int i = 0; i < Model.Comment1.ToList().Count(); i++)
            {
                 @Html.EditorFor(m => m.Comment1.ToList()[i])
            }
            </table>
           <a id="addReply" href="#">Add Reply</a>

    </td>
}

<a ...>链接用于通过Ajax获取条目行,并将它们附加到相应的表中。

提交时,绑定仅适用于第一个嵌套级别(A.B.Comments,但不适用于A.B.Comments中对象的注释)。原因可能是由@using (Html.BeginCollectionItem("B.Comment"))行引起的,该行仅为1级深度生成索引。

如果有人能给我一个关于如何在这些情况下允许无限制嵌套的建议,我将非常感激。有没有办法动态修改Html.BeginCollectionItem(ARG)?

中的参数

干杯

编辑:简化的ViewModel,根据要求

public partial class A
{
    (...)
    public int BID{ get; set; }
    public virtual B B{ get; set; }
    (...)
}

public partial class B
{
    (...)
    public virtual ICollection<Comment> Comment { get; set; }
}

public partial class Comment
{
    (...)
    public Nullable<int> ParentID { get; set; }
    public virtual ICollection<Comment> Comment1 { get; set; }
    public virtual Comment Comment2 { get; set; }
    public virtual B B { get; set; }
    public Nullable<int> BID { get; set; }
}

附录:

我最终创建了一个不同的BeginCollectionItem()Html助手,它不会为生成的html的名称和id添加前缀。

E.g:

我的方式,如果我在评论中有评论,Html助手会生成这样的标签:name="*B.Comment[521cfe57-23aa-42d4-9b63-b7fcdd8799c3].*B.Comment.index" 我的新方法只生成name="Entity.Comment.index",它允许绑定正常工作。

AlbertoLeón通过提醒我,我不必实际进行深入绑定(例如,将评论的评论绑定到其父级等等)作为捕获评论与评论之间的关系,从而给了我正确的提示。 B对象足以让绑定按我的意愿工作。

2 个答案:

答案 0 :(得分:1)

你是以复杂的方式做到这一点。 几年前,我设计了Bside社交引擎,因为没有创建而遗憾地死了。

我发现了同样的问题,它有一个非常简单的解决方案。

您需要为每个内容分配一个guid,并将每个评论视为新内容,这样您就可以随时搜索guid内容。 然后,您只需要使用属性Comments和方法Add,Delete,Edit

创建ICommentable接口

然后你需要继承ICommentable的A类,你需要编写实现。对于B来说也一样。

然后在业务层中,您可以从数据库或存储方式获得A和B.并在数据库中搜索A和B注释。当你得到它时,你需要搜索评论的评论。

因此,在存储方式中,评论始终是评论。关于与评论相关的内容项目没有意义。

关于使用ajax的用户界面,我使用了jQuery。 所以不要试图绑定。 将每个评论视为独立对象。 添加注释和保存的每个添加按钮只能引用注释。您只需要使用新注释向MVC方法发送表单。不要忘记父内容项(类A,或B或任何Comment对象)的guid

答案 1 :(得分:0)

您可以使用ViewData.TemplateInfo.GetFullHtmlFieldName()或ViewData.TemplateInfo.HtmlFieldPrefix来检索当前模型的完整路径