GOAL:
Have a hierarchy of nested elements with unlimited depth.
PROBLEM:
I have a class A, which includes an instance of a class B.
Class B has a list of Comment objects. Each Comment may have a list of "child" Comments.
Therefore, we have a tree-like structure with unlimited-depth nesting (e.g. A.B.Comments[1].Comments[0].Comments[5]....).
Class A Editor View calls:
@Html.EditorFor(m=>m.B)
Class B's Editor Template has (simplified):
<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>
And each Editor Template for the Comment class consists of (simplified):
<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>
}
The <a ...>
links are used to get entry rows via Ajax and append them to the corresponding tables.
When submitting, the binding only works for the first nesting level (A.B.Comments, but not for Comments made on objects in A.B.Comments). The reason, is likely to be due to the @using (Html.BeginCollectionItem("B.Comment"))
line, which is generating the indexes only for 1 level of depth.
I'd be very thankful if anyone could give me a suggestion on how to allow unlimited nesting given these circumstances. Is there a way to dynamically modify the argument in Html.BeginCollectionItem(ARG)?
Cheers
EDIT: The simplified ViewModels, as requested
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; }
}
ADDENDUM:
I ended up creating a different BeginCollectionItem() Html helper that doesn't keep adding prefixes to the generated html's names and id's.
E.g.:
The way I had, if I had a comment inside a comment, the Html helper would generate tags like this: name="*B.Comment[521cfe57-23aa-42d4-9b63-b7fcdd8799c3].*B.Comment.index"
My new method just generates name="Entity.Comment.index"
which allows the binding to work correctly.
Alberto León gave me the right hint by reminding me that I don't have to actually do an in-depth binding (for instance, bind a comment's comment to its parent and so forth) as capturing the relationship between the comment and the B objects is enough for the binding to work as I wish.