Search code examples
asp.netrepeaternested-repeater

How can I Implement N level nested Repeater control in asp.net?


I want to achieve n level data hierarchy in using repeater control in asp.net. Is there any solution to achieve that hierarchy ?


Solution

  • For this answer I'm going to suggest creating your template programmatically - see here: https://msdn.microsoft.com/en-us/library/aa289501 . There is probably some way to use templates that have been created in markup, but this seems easier, and definitely more flexible.

    I start out with a page with just a repeater (not template)

    <body>
        <form id="form1" runat="server">
        <div>
            <asp:Repeater runat="server" ID="TestRepeater">
            </asp:Repeater>
        </div>
        </form>     
    </body>
    

    and a data class

    public class DataClass
    {
        public string Name { get; set; }
        public List<DataClass> Children { get; set; }
    }
    

    For the template we use the following class:

    public class DataTemplate : ITemplate
    {
        public void InstantiateIn(Control container)
        {
            var name = new Literal();
            var repeater = new Repeater();
    
            name.DataBinding += BindingLiteral;
            repeater.DataBinding += BindingRepeater;
    
            // this here makes it recursive
            repeater.ItemTemplate = new DataTemplate();
    
            container.Controls.Add(name);
            container.Controls.Add(repeater);
        }
    
        private void BindingLiteral(object sender, System.EventArgs e)
        {
            var name = (Literal)sender;
            var container = (RepeaterItem)name.NamingContainer;
            name.Text = String.Concat("<h2>", DataBinder.Eval(container.DataItem, "Name").ToString(), "</h2>");
        }
    
        private void BindingRepeater(object sender, System.EventArgs e)
        {
            var name = (Repeater)sender;
            var container = (RepeaterItem)name.NamingContainer;
            name.DataSource = DataBinder.Eval(container.DataItem, "Children");
        }
    }
    

    Obviously you'll want to use a more sophisticated template. Notice that if you currently have a template in markup, you could simply take the code that has been generated by the markup parser, and adapt it to your needs.

    Now in the code behind of the page we simple assign the ItemTemplate and DataSource:

    public partial class Test : System.Web.UI.Page
    {
        protected void Page_Init(object sender, EventArgs e)
        {
            TestRepeater.DataSource = GetTestData();
            TestRepeater.ItemTemplate = new DataTemplate();
            TestRepeater.DataBind();
        }
    }
    

    Nice thing about this is your template is just a class, so you could add a public Int32 Depth { get; set; } to it, and change the generated controls based on your depth.