Insert Dynamically Added User Controls

Posted on 2009-02-19
Last Modified: 2013-11-07
Hello folks--this is my very first post! I'm pretty desperate so I'm going above and beyond my standard googling. I believe this is an advanced or expert-level .NET question.

The problem is that I have built a .NET web application that needs to be able to insert user controls dynamically into the middle of a list. I'm quite comfortable with dynamic controls so long they only need to be added to the end of the list (ie: I'm familiar with articles like this: However, if I need to add a UserControl to the front of a Controls collection or somewhere in the middle I'm pretty much lost since the UniqueID of the control is thrown off.

As a simplified example, let's say that i have a Panel to which I am adding a list of UserControls called MyControl.ascx. I also have some event that can get fired on the page to that needs to dynamically insert a MyControl.ascx into the specified index of the Controls collection of the panel. I also have one or more events on MyControl.ascx to which I need to subscribe. This means that the controls need to be loaded BEFORE the events on these controls would fire or else they will not fire. If you don't know to what I'm referring then I either worded the question poorly or this question might be too difficult for you :)

Below is some C# pseudocode to demonstrate the issue. The problem is that the Controls.AddAt(index, control) method does NOT adjust the UniqueID values of the controls accordingly. For example, consider the following controls in a Controls collection:

Control index             UniqueID
0                                ctl00
1                                ctl01
2                                ctl02

If i do a Controls.AddAt(0, newControl) then the Controls collection looks something like this:

Control index             UniqueID
0                                ctl03      <== the controls' unique IDs do not shift!
1                                ctl00
2                                ctl01
3                                ctl02

This means that upon reloading the page any events that get fired from these controls will be attached to the wrong controls! For example, if the user clicks on a button in ctl03 it will attach to the control that gets loaded 3rd on the postback.

Please help--this one is killing me. If you need more information or have questions please let me know and I'd be happy to provide more info. I GREATLY appreciate your help!
//--on init i just need to pull the records from the DB, turn them into a MyControl.ascx,

       //   and then add them to my panel

        protected override void OnInit(EventArgs e)



            //--get my List<SomethingFromDB> and iterate through, adding controls to the

            //   control collection

            List<SomethingFromDB> myList = remoteService.GetSomeListFromTheDB();

            foreach(SomethingFromDB something in List<SomethingFromDB>)


                   //--load a new MyControl.ascx

                  MyControl myControl = (MyControl )LoadControl("~/Controls/MyControl .ascx");

                   //--populate the values of myControl with the "something"


                  //--dynamically add the control to my panel


                  //--subscribe to event

                  myControl.SomeArbitraryEvent += new EventHandler(MyArbitraryHandler);


        //--This event gets fired by a magical control on the page and passes

        //   a new SomethingFromDB which needs to be inserted into the DB

        //   and then dynamically inserted into the Controls collection at the specified

        //   index

        private void SomeOtherControl_ClickInsert(object sender, MyControlEventArgs e)


              //--insert this record into the DB             


              //--dynamically load this control

              MyControl myControl = (MyControl )LoadControl("~/Controls/MyControl .ascx");

               //--get the index into which we will be inserting this control

               int index = e.NewIndex;


                  //--dynamically add the control to my panel at the specified index.

                  this.myPanel.AddAt(index, myControl);


Open in new window

Question by:jakejgordon
    LVL 12

    Expert Comment

    In this case, I'd probably use a session variable (or other practical mechanism) to hold the desired load-order of the controls that is updated when a control is added.  And immediately after they are initially loaded in the wrong order, remove and re-load them in the order specified in the session variable. You'll need a mechanism to manage the session variable, but it might do in a pinch.

    However, it sounds like there may be a better approach.

    Author Comment

    Thanks for the feedback funwithdotnet. There are definately some hacks I can pull off to get this to work but I'm most interested in figuring out the "right" way to do this as I'm in the process of building a huge website where this concept will be re-used over and over.

    I'm looking for an eloquent way to either reset or manipulate unique IDs on a Controls collection or delay the assignment of the unique IDs--or something else along those lines.
    LVL 12

    Expert Comment

    The Control.UniqueId is an automatically-populated, readonly property. You could probably reset it by removing and reloading. That's about all you can do.

    Since a specific load-order is required and changes, some way of tracking it must be done. whether it be by session, viewstate, datasource, etc.  I'd probably name my controls and use a custom load-order mechanism to load them every time, by name.

    Author Comment

    Unfortunately, removing the controls doesn't restart the UniqueID counter (ex: ctl00, clt01, clt02, etc.) If i delete the entire parent container and re-add it then i still have the same problem. For example, if i have a page with a panel that has three controls, i can remove one of the three controls on the panel and re-add it, but the control will end with ctl03 (instead of ctl02). If i remove the entier panel and re-add it the child controls will reset, but now the panel will be named ctl01 instead of ctl00.

    As for the second part of your comment I'm not exactly sure what you mean. I know the order that the controls need to be loaded and I can find where I need to insert a control in the collection... the problem is that even though the controls will be in the same order after posting back, the UniqueID for those controls will be different.
    LVL 12

    Accepted Solution

    I mean I think you'll have to do what needs to be done without depending on the UniqueID, because you can't depend on the UniqueID, except knowing the UniqueID will list the controls hierarchically.  I suggest using the Control.ID property for managing the controls. Control.ID is the programmatic identifier (name) .

    Author Comment

    Whether I'm actually writing code that directly depends on the UniqueID or not, .NET indirectly uses the UniqueID to link together the events that were fired on the previous postback with the controls get loaded on the new postback. Taking my previous example of:

    On initial Page Load (Page.IsPostback == false)

    Control index             UniqueID            Value
    0                                ctl00                  value1
    1                                ctl01                  value2
    2                                ctl02                  value3

    After a postback (Page.IsPostback == false) from some other control that wants to insert the control at index 0:

    If i do a Controls.AddAt(0, newControl) then the Controls collection looks something like this:

    Control index             UniqueID            Value
    0                                ctl03                  value0          <== the controls' unique IDs do not shift!
    1                                ctl00                  value1
    2                                ctl01                  value2
    3                                ctl02                  value3

    So if i were to click on a linkbutton in the control with Value == value0 and UniqueID == ctl03, the controls would be ordered like the following on post-back and the UniqueIDs would not be in the order i want. This will cause the click event to attach to the wrong control:

    Control index             UniqueID            Name
    0                                ctl00                  value0         <== the control i wanted to throw the event
    1                                ctl01                  value1
    2                                ctl02                  value2
    3                                ctl03                  value3          <== the actual control to which the event is attached

    If i didn't have to handle events from these dynamic controls this probably wouldn't be a problem.

    Author Comment

    After playing around some more I think i see what you are getting at. Since I'm actually not setting the ID of the dynamically loaded control BEFORE adding it to the panel it is just using it's own numbering. If i assign my own ID (ex: a primary key value) then it will not use the auto-incremented value. Problem solved! Thanks a ton funwithdotnet!

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    Looking for New Ways to Advertise?

    Engage with tech pros in our community with native advertising, as a Vendor Expert, and more.

    Suggested Solutions

    Flash ( has evolved over the years to where it has become a masterful tool for displaying content screen.  It has excellent layout placement, UI precision as well as rendering capabilities. This, along with t…
    Summary Displaying images in RichTextBox is a common requirement with limited solutions available. Pasting through clipboard or embedding into RTF content only support static images.  This article describes how to insert Windows control objects int…
    Hi everyone! This is Experts Exchange customer support.  This quick video will show you how to change your primary email address.  If you have any questions, then please Write a Comment below!
    Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.

    760 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    8 Experts available now in Live!

    Get 1:1 Help Now