FAQ: Why do dynamic controls disappear on postback and not raise events?

One common error that many have run into when first starting out with creating dynamic page controls is an incorrect assumption that those dynamic controls will survive page postbacks.

For example - a common scenario is to:

Declare a button (Button1) in your page markup

Add an event handler for Button1 and in that handler, create a new dynamic button (Button2)

Wire up and event handler for Button2

Page loads an you see Button1

Click on Button1 and the page posts-back Button1's Click event fires and you now see Button1 and Button2

Click on Button2 and...the page posts-back, Button2 disappears and no event for Button2 is raised.

And about now you may be wondering - What happened to Button2?

Since Button2 is not part of your pages declared markup, the framework has no way to know if it should be recreated or not on a postback. You'll need to keep track of the fact that you have created dynamic control(s) and you will need to add the necessary
code to recreate those dynamic control(s) yourself on all subsequent page postbacks. In order for your dynamic control(s) to work correctly, you'll need to get them all recreated by the Page_Load event
at the latest.

The following example demonstrates how to toggle between 2 different sets of dynamic controls and how to handle events raised from those controls. In this example, I've chosen ViewState as the place where i will store the information needed to know which
dynamic controls need to be recreated on a postback.

Partial Class DynamicControls
Inherits System.Web.UI.Page
Const ALPHABET_SELECTION As String = "ALPHABET"Const NUMBER_SELECTION As String = "NUMBERS"Const VIEWSTATEKEY_DYNCONTROL As String = "DynamicControlSelection"'store property value in viewstate so that it will survive postbacks
Private Property DynamicControlSelection() As String
Get
Dim result As String = ViewState.Item(VIEWSTATEKEY_DYNCONTROL)
If result Is Nothing Then'doing things like this lets us access this property without
'worrying about this property returning null/Nothing
Return String.Empty
Else
Return result
End If
End Get
Set(ByVal value As String)
ViewState.Item(VIEWSTATEKEY_DYNCONTROL) = value
End Set
End Property
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles Me.Load
'running this code on every page_load - even when it's a postback
'check our page property (that we stored in viewstate) to see
'if we need to load a specific set of dynamic controls
Select Case Me.DynamicControlSelection
Case ALPHABET_SELECTION
CreateDynamicAlphabetLinks()
Case NUMBER_SELECTION
CreateDynamicNumberButtons()
Case Else'no dynamic controls need to be loaded...yet
End Select
End Sub
Private Sub onClick(ByVal sender As Object, ByVal e As EventArgs)
'all of the dynamic linkbuttons/buttons will trigger this event handler
'since we used both linkbuttons and regular buttons for our dynamic controls,
'we will cast the sender control to an interface that is common to both
'of those button controls - the IButtonControl interface
Dim btn As IButtonControl = DirectCast(sender, IButtonControl)
Me.lblClickResult.Text = _
String.Format("You clicked - CommandName: {0} CommandArgument: {1}", _
btn.CommandName, btn.CommandArgument)
End Sub
Protected Sub cmdAlphabet_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles cmdAlphabet.Click
'user is selecting to show the dynamic Alphabet buttons
Me.CreateDynamicAlphabetLinks()
End Sub
Protected Sub cmdNumbers_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles cmdNumbers.Click
'user is selecting to show the dynamic Number buttons
Me.CreateDynamicNumberButtons()
End Sub
Private Sub CreateDynamicAlphabetLinks()
'clear the placeholder first - in case something else was dynamically loaded
Me.PlaceHolder1.Controls.Clear()
'dynamically create a series of linkbuttons
For keycode As Integer = 65 To 90 'one for each letter in the alphabet
Dim lnk As New LinkButton
'assign the ID ourself to make sure it is consistent
'if you let the framework assign it, the dynamic control may
'not behave correctly
lnk.ID = "alpha_" & keycode.ToString
lnk.Text = Chr(keycode)
'we'll add a CommandName and a CommandArgument
'so we can determine what was clicked when the event is raised
lnk.CommandName = "ALPHABET"
lnk.CommandArgument = Chr(keycode)
'have them all use the same event handler
AddHandler lnk.Click, AddressOf onClick
'add these dynamic controls to our strategically place placeholder control
'the position of the placeholder determines
'where on the page the dynamic controls will appear
Me.PlaceHolder1.Controls.Add(lnk)
Me.PlaceHolder1.Controls.Add(New LiteralControl(" ")) 'space them out
Next'VERY IMPORTANT -> remember that we created these controls for the next postback
Me.DynamicControlSelection = ALPHABET_SELECTION
End Sub
Private Sub CreateDynamicNumberButtons()
'clear the placeholder first - in case something else was dynamically loaded
Me.PlaceHolder1.Controls.Clear()
'dynamically create a series of button controls
For number As Integer = 0 To 25
Dim btn As New Button
'assign the ID ourself to make sure it is consistent
'if you let the framework assign it, the dynamic control may
'not behave correctly
btn.ID = "number_" & number.ToString
btn.Text = number.ToString
'we'll add a CommandName and a CommandArgument
'so we can determine what was clicked when the event is raised
btn.CommandName = "NUMBER"
btn.CommandArgument = number.ToString
'have them all use the same event handler
AddHandler btn.Click, AddressOf onClick
'add these dynamic controls to our strategically place placeholder control
'the position of the placeholder determines
'where on the page the dynamic controls will appear
Me.PlaceHolder1.Controls.Add(btn)
Me.PlaceHolder1.Controls.Add(New LiteralControl(" ")) 'space them out
Next'VERY IMPORTANT -> remember that we created these controls for the next postback
Me.DynamicControlSelection = NUMBER_SELECTION
End Sub
Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles Me.PreRender
Me.lblViewStateValue.Text = Me.DynamicControlSelection
End Sub
End Class

Re: FAQ: Why do dynamic controls disappear on postback and not raise events?

It is important to note that it is not sufficient to re-create the dynamic controls on all subsequent page postbacks.
You need to re-create them with the same ID's (as shown in the code above). The ID's are important for the event mechanism.

If you don't assign ID's, the ASP.NET engine will assign ID's automatically (something like ctl_01, ctl_02, etc.), and sometimes these ID's may be different before and after the postback (for instance if the number of controls has changed in the mean time).

This remark is already stated in the code above, but I think it is important to keep it in mind as a general rule before you start coding dynamic controls.

Re: FAQ: Why do dynamic controls disappear on postback and not raise events?

While you can create dynamic controls in either Page_Init or Page_Load, I chose Page_Load as I was using ViewState to store a value that indicated which set of dynamic controls should be loaded. ViewState values are available in Page_Load - but they are
not available during the Page_Init event. If the control creation logic were to be moved to Page_Init, then the example i posted would not work.

Re: FAQ: Why do dynamic controls disappear on postback and not raise events?

First we need a simple page that contains a PlaceHolder control named PlaceHolder1. In the Page_Init event of our page we can call a separate class to create a dynamic button.

Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
'ask a separate class to create a button control in a designated placeholder
'note that it's very important that the dynamic control is created on each and every
'postback and that the dynamic control also has a consistent control ID.
Dim buttonCreator As New DynamicButtonCreator
buttonCreator.CreateButton(Me.PlaceHolder1)
End Sub

So now we need that separate class to both create the dynamic button control and to handle the click event from it.

Re: FAQ: Why do dynamic controls disappear on postback and not raise events?

If you need to access viewstate you can initalize/create dynamic controls in LoadViewState which occurs between Page_Init and Page_Load. In LoadViewstate, access viewstate properties and create the controls , after the base.LoadViewstate call.

Re: FAQ: Why do dynamic controls disappear on postback and not raise events?

Whether the Page.IsPostBack property returns true or false is usually not the issue. The page might be in a postback and still not need to have any dynamic controls loaded. It might require a specific interaction with the page that causes the first dynamic
control to be loaded. Ultimately, it is important to keep track of what dynamic controls (if any) may have been loaded and then continue to load them early in the page life-cycle on all subsequent postbacks.

If Button "Add New" didn't press i delete the last dropdownlist beacuse another event happened and decrease the session counter by one.

My question is " Can i make my code better ?" , i don't want to create and delete controls after . I decided to do this because the "Add New" Event fires between Page_Load and PreRender steps and the only way to create a control that its handlers are registered
is to create before PreRender. So I create it at Init It could be in Page_Load as well and then if the button pressed i don't delete it.

Re: FAQ: Why do dynamic controls disappear on postback and not raise events?

When I first started working with the Accordian control in an update Panel I had this issue. I was data binding a lot of things so as a result, I kept having to use a lot of caching in order to not over hit the database but also to retain the controls
on the page. This is a pretty good way to do it from what I see. I need to figure out VB a bit more as I really only us C#.

Re: FAQ: Why do dynamic controls disappear on postback and not raise events?

This is amazing article explaing in detail how to get the dynamic controls value after the potback occurs.

I am working on C# and I can't seem to find AddHadler and could't convert your code to C# because of other issues. Can you please detail me how do I convert your code into C# or if you have a C# version of the above code, can you please provide me.

Re: FAQ: Why do dynamic controls disappear on postback and not raise events?

miteshsura

I have tweaked this to addi usercontrol dynamically. I was able to add on buton click event 1 time, but I wanted to add usercontrol N number time. N->> number of button hits by the end user.

Now I need to fig out how to retain the value using viewstate in my usercontrol.

You could add your counter to viewstate and simply keep track of the number of controls you need to dynamically create. Then on each postback during the Page_Load event, you check your counter that was stored in viewstate and recreate the number of dynamic
controls indicated by that counter. In order to insure that the dynamic controls behave properly, you need to also insure that they get consistent ID's. So i would use the counter to help create those controls ids. so your controls would end up getting
ids like; dynamicControl1, dynamicControl2, dynamicControl3 ...

'this property will be used to keep track of
'how many dynamic controls were created.
Private Property TextboxCounter() As Integer
Get
Dim o As Object = ViewState("TextboxCounter")
If o Is Nothing Then Return 0
Return DirectCast(o, Integer)
End Get
Set(ByVal value As Integer)
ViewState("TextboxCounter") = value
End Set
End Property
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'recreate dynamic controls on all postback by page_load at the latest
'we use page_load instead of init so that we can access viewstate.
If Page.IsPostBack Then
For i As Integer = 1 To TextboxCounter
Dim ctrl As New TextBox
'It's very important to specify the controls ID
ctrl.ID = "dynamicTextBox" & i
Me.PlaceHolder1.Controls.Add(ctrl)
Next
End If
End Sub
Protected Sub cmdAddTextbox_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdAddTextbox.Click
'increment counter
TextboxCounter += 1
'add new dynamic control
Dim ctrl As New TextBox
ctrl.ID = "dynamicTextBox" & TextboxCounter
Me.PlaceHolder1.Controls.Add(ctrl)
End Sub
Protected Sub cmdProcessControls_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdProcessControls.Click
'loop through any textbox controls and see what they contain
For Each ctrl As TextBox In Me.PlaceHolder1.Controls
Response.Write(String.Format("Control ID: {0}, Text: {1} <br/>", ctrl.ID, ctrl.Text))
Next
End Sub

Re: FAQ: Why do dynamic controls disappear on postback and not raise events?

this is exactly what I was looking for, I was trying to achieve that via page init event and using __EVENTTARGET, but for some reasons for button __EVENTTARGET was null, than I read somewhere button and image button do not support that. I replaced that
with link button, but FindContorl would't find the link button id, because I was using master page.. your solution worked like butter on hot pan!! thanks

Re: FAQ: Why do dynamic controls disappear on postback and not raise events?

If Viewstate is used to store the value of dynamic contrlols then Page_Load is the event to be used. ViewState values are available in Page_Load - but they are not available during the Page_Init event.

Re: FAQ: Why do dynamic controls disappear on postback and not raise events?

i use the example to adding N number of dynamic controls to a page . I want to create dropdownlist populate by Dataset and in cmdProcessControls_Click I wanto to show the item choise by user in dropdownlist but I don't get the same behaviour. When Click
in cmdProcessControls button i view dropdownlist without item and label control empty. If I use dropdownlist populate by listitems It works.

Re: FAQ: Why do dynamic controls disappear on postback and not raise events?

From personal experience, I nearly killed myself over trying to sort out problems that I had with adding ListItems to a Drop Down List in a repeater. The code seemed to work perfectly fine outside of the repeater with the ListItems being persisted and the
_SelectedIndexChanged event being raised and other what not. I finally figured out that instead of having the Drop Down List in the markup and adding the ListItems to it, that I needed to just have an asp : placeholder in the content and the create the entire
Drop Down List from start to finish in the code behind via the _ItemDataBound event. I had checked everything including EnableViewState on the control, on the Repeater on the Page.

Of course now that its working, the whole thing has to be scrapped given that I didn't factor in how the number of items in the repeater and the Drop Down List would impact the load time of the page

Re: FAQ: Why do dynamic controls disappear on postback and not raise events?

I am creating one tabcontainer and 13 tabpanels dynamically in page_init.I have also created iframe in each tabpanel dynamically in page_init.Now how can i access first iframe's id.I am getting only last iframe's id once page loads.

The mypage.aspx.cs code is:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient;
using AjaxControlToolkit;
using System.Configuration;

Re: FAQ: Why do dynamic controls disappear on postback and not raise events?

Is it possible that this approach doesn't work for custom events? I've got a ul to which I'm programmatically adding (ASP.net user control) lis. I'm re-adding these user controls in the Page_Load event and 'ordinary' events (that is: LinkButton.Clicks) work
fine - only my custom events somehow lose their handlers during the postback.

Here is how I'm adding the controls to the list (the IDs are persistent over postbacks):

This is the jist of using viewsates to keep post back variables in C#. This is from my code, it is showing you how to use the functionality. Manipulate this how you want, you can use any type (does not have to be bool etc).

Re: FAQ: Why do dynamic controls disappear on postback and not raise events?

Very nice article. Indeed of much help !
I would like to add a bit of my learning here.

I noticed that, the dynamically added control was not retaining the values on the Very First Postback. For example, if you are debugging, then when the page gets loaded for the first time, you may see that the Page' Load or Init event does not get executed,
on the server.

This happens, because, by default, the page is cached by the browser and the browser serves this Page's HTML directly from its cache. So to avoid that, just add the following ASP Code in your ASPX file:-

Re: FAQ: Why do dynamic controls disappear on postback and not raise events?

Recently i hav developed a Project with dynamic Controls.I can see you the demo of that project actually that project is of my Company but developed by me...It is totally dynamic..Please add me on gmail my gmail address is mangesh.gangwar@gmail.com.I can
send you the video of that project.I am using XML and sql server for databse to managing dynamic controls.There are also dynamic javascript validation for dynamic controls.

Re: FAQ: Why do dynamic controls disappear on postback and not raise events?

I am using mainly text box and dropdown list with javascript validation...but my controls are displaying in GridView.All the things in my project are dynamic and i am using xml.I am managing controls and validation throgh xml file.user can create template
according to his/her requirements.