Dynamically adding a user control to a repeater

11,176

I had done this a long time ago for creating nested reports using Accordions.

In Index, when you want to dynamically add User Control instances:

// Declare Placeholder    
PlaceHolder ph = (PlaceHolder)e.Item.FindControl("SubItemPlaceholder")

// Adding some literal controls to header
ph.Controls.Add(new LiteralControl("This is the accordion header!!"));

// Declare new control variable
crt = new Control();

// Load up your User Control
crt = LoadControl("~/MyControl.ascx");

// Check if it has loaded properly
if (crt != null)
{
    // GET / SET any custom properties of the User Control
    ((myClass)crt).title = "Welcome";

    // Add the new User Control to the placeholder's controls collection
    ph.Controls.Add(crt);
}

Note: In the User Control, you must add the "ClassName" in the declaration tag

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="MyControl.ascx.cs" Inherits="myTest" ClassName="myClass" %>

Also, any properties you wish to expose when creating instances dynamically, you declare them as follows:

public string title { get; set; }

So if you want to force a value when creating for "repMyClass" you can set it as a property and assign whatever value you want to it programmaticaly.

Share:
11,176
Jeremy
Author by

Jeremy

Software Developer

Updated on June 19, 2022

Comments

  • Jeremy
    Jeremy almost 2 years

    I have a class (MyClass) which represents a nested hierarchy, so the class has a property which is a collection of MyClass. MyClass also has a title property

    To show it on a web page, I was hoping to create a user control which had a repeater. In the item template I would have literal to display the title property, and on the ItemCreated event of the repeater, I would create a new instance of the usercontrol, and add it into the current item in the repeater.

    My problem is, when the Page_Load event in the usercontrol fires, if the control was dynamically added, the repMyClass repeater poroperty is null, even if I call EnsureChildControls. Am I missing something here? If I create a repeater and drop my userctonrol in the item template it works fine. My can't I get this to work dynamically?

    User Control:

    <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MyControl.ascx.cs" Inherits="MyControl" %>
    Items:<br/>
    <asp:Repeater ID="repMyClass" runat="server" EnableViewState="false" 
        OnItemCreated="repMenuItems_ItemCreated">
        <HeaderTemplate><ul><HeaderTemplate>
        <ItemTemplate>
            <li><%# Eval("Title") %>
                <div><asp:PlaceHolder ID="SubItemPlaceholder" runat="server" /></div>
            </li></ItemTemplate>
        <FooterTemplate></ul></FooterTemplate>
    </asp:Repeater>
    

    User Control Code:

    public partial class MyControl: System.Web.UI.UserControl
    {
        public IEnumerable<MyClass> ChildItems { get; set; }
        protected void Page_Load(object sender, EventArgs e)
        {
            this.repMyClass.DataSource = ChildItems;
            this.repMyClass.DataBind();
        }
    
        protected void repMenuItems_ItemCreated(object Sender, RepeaterItemEventArgs  e)
        {
            if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
            {
                //Get the MyClass instance for this repeater item
                MyClass mcCurrent = (MyClass)e.Item.DataItem;
    
                //If the MyClass instance has child instances
                if (mcCurrent.Children != null && mcCurrent.Children.Length > 0)
                {
                    //Add a new user control and set it's property so it can bind
                    PlaceHolder ph = (PlaceHolder)e.Item.FindControl("SubItemPlaceholder");
    
                    MyControl ctl = (MyControl)Page.LoadControl(typeof(MyControl),new object[] {});
    
                    ctl.ChildItems = mcCurrent.Children;
                    ph.Controls.Add(ctl);
                }
            }
        }
    }
    
  • Jeremy
    Jeremy over 12 years
    The problem is, my user control has it's own child controls (a repeater in this case). In the page_load event of the user control, the repeater variable is actually null. I can't set it myself, the asp.net framework needs to.
  • Jeremy
    Jeremy over 12 years
    The problem is, my user control has it's own child controls (a repeater in this case). In the page_load event of the user control, the repeater variable is actually null. I can't set it myself, the asp.net framework needs to.
  • vvohra87
    vvohra87 over 12 years
    @Jeremy : Sure you can. Just create a property of type repeater. You can then access it, instantize it, do whatever you want with it. Please clarify - according to me you should have a public property in the UserControl, in the Page Load of the UserControl you should be using that public property to bind data to the repeater. Is that correct?
  • Meligy
    Meligy over 12 years
    The theory is that you shouldn't need to use the load, use the setter instead. Another alternative is in the answer update, that one might fix the issue. I think the problem is the event used, this has very good probability of being the issue.