2

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

Jaimin Soni
  • 990
  • 12
  • 29
  • 1
    Short answer: Yes. Longer answer: yes, but we prefer to see what you've tried so far, and where you're having trouble getting it working – freefaller Mar 31 '15 at 09:01
  • I have one repeater control that contain another repeater control and second contain user control that have another repeater control. I want to continue that hierarchy up to n level using that user control. – Jaimin Soni Mar 31 '15 at 09:03
  • Are you wanting to implement a nested repeater with however many levels as are necessary to represent your data - basically a recursive template? Are you trying to render some kind of treeview? – Menno van den Heuvel Mar 31 '15 at 09:05
  • yes. recursive template using repeater control and user control – Jaimin Soni Mar 31 '15 at 09:06

2 Answers2

2

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.

Menno van den Heuvel
  • 1,811
  • 13
  • 23
1

Another solution, without creating the template programmatically :

Using a simple data class :

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

In the ASPX markup create your parent repeater, put your item display code in the ItemTemplate, and add a second "empty" repeater :

<body>
    <form id="form1" runat="server">
    <div>
        <asp:Repeater runat="server" ID="ParentRepeater" OnItemDataBound="Repeater_ItemDataBound">
            <ItemTemplate>
                <asp:Literal runat="server" Text="<%# Eval("Name") %>"></asp:Literal>
                <asp:Repeater runat="server" ID="ChildRepeater" OnItemDataBound="Repeater_ItemDataBound" Visible="false">
                </asp:Repeater>
            </ItemTemplate>
        </asp:Repeater>
    </div>
    </form>     
</body>

And in the code-behind :

protected void Repeater_ItemDataBound(object sender, RepeaterItemEventArgs e) {
    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) {
        DataClass currentItem = (DataClass)e.Item.DataItem;

        if (currentItem.Children.Count > 0) {
            Repeater ChildRepeater = (Repeater)e.Item.FindControl("ChildRepeater");

            ChildRepeater.DataSource = currentItem.Children;
            ChildRepeater.ItemTemplate = ParentRepeater.ItemTemplate;
            ChildRepeater.Visible = true;
            ChildRepeater.DataBind();
        }
    }
}
Jereck
  • 11
  • 3