You can do this using recursive code. The actual solution will change depending on what your data looks like and how you access it, but this is the gist. All files are in the root of the site.
CommentObject.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MyNamespace
{
public class CommentObject
{
public int ID { get; set; }
public int ParentID { get; set; }
public string Author { get; set; }
public string Body { get; set; }
public List<CommentObject> Replies { get; set; }
}
}
Comment.ascx
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Comment.ascx.cs" Inherits="MyNamespace.Comment" %>
<div style="border: 1px dashed #aaaaaa; margin-left:30px;">
<h2><asp:Literal ID="LiteralAuthor" runat="server" /></h2>
<div><asp:Literal ID="LiteralBody" runat="server" /></div>
<asp:PlaceHolder ID="PlaceReplies" runat="server" />
</div>
Comment.ascx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace MyNamespace
{
public partial class Comment : System.Web.UI.UserControl
{
public CommentObject CommentObject { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
LiteralAuthor.Text = this.CommentObject.Author;
LiteralBody.Text = this.CommentObject.Body;
}
}
}
TestPage.aspx
<form id="form1" runat="server">
<asp:PlaceHolder ID="PlaceComments" runat="server" />
</form>
TestPage.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
List<CommentObject> comments = new List<CommentObject>();
comments.Add(new CommentObject { ID = 1, Author = "Author A", Body = "Comment 1" });
comments.Add(new CommentObject { ID = 2, Author = "Author B", Body = "Comment 2" });
comments.Add(new CommentObject { ID = 3, Author = "Author C", Body = "Comment 3" });
comments.Add(new CommentObject { ID = 4, Author = "Author D", Body = "Comment 4" });
CommentObject comment = comments.Single(c => c.ID == 2);
comment.Replies = new List<CommentObject>();
comment.Replies.Add(new CommentObject { ID = 5, Author = "Author A", Body = "Comment 5" });
comment.Replies.Add(new CommentObject { ID = 6, Author = "Author C", Body = "Comment 6" });
comment.Replies.Add(new CommentObject { ID = 7, Author = "Author D", Body = "Comment 7" });
comment = comment.Replies.Single(c => c.ID == 6);
comment.Replies = new List<CommentObject>();
comment.Replies.Add(new CommentObject { ID = 8, Author = "Author A", Body = "Comment 8" });
comment.Replies.Add(new CommentObject { ID = 9, Author = "Author F", Body = "Comment 9" });
ShowComments(PlaceComments, comments);
}
private void ShowComments(PlaceHolder placeHolder, List<CommentObject> comments)
{
foreach(CommentObject comment in comments)
{
Comment ctlComment = (Comment) LoadControl("~/Comment.ascx");
ctlComment.CommentObject = comment;
placeHolder.Controls.Add(ctlComment);
if (comment.Replies != null && comment.Replies.Any())
{
ShowComments((PlaceHolder)ctlComment.FindControl("PlaceReplies"), comment.Replies);
}
}
}