Dynamically Added DropDownlists Are Not Firing SelectedIndexChanged Event
This is a common issue and it's related to the page life cycle:
Take a look at the following questions:
Click events on Array of buttons
Button array disappears after click event
Dynamically create an ImageButton
Now the basic steps to remember when creating dynamic controls are:
- Dynamic controls should be created in the
PreInit
event when you are not working with a master page, if you are, then create the controls in theInit
event - Avoid setting properties that can be changed in each post in these events because when the view state is applied (in a post event) the properties will be overridden
- Dynamic controls must be created every time the page is posted, avoid this
if(!this.IsPostBack) this.CreatemyDynamicControls();
- When you create the controls in the
PreInit
orInit
events, their states will be automatically set in a post event, which means in theLoadComplete
event your controls will contain their state back even when you create them again in each post and even when you did not explicitly set their state. Note this behavior is different when you are dealing with controls created at design time, in that case, the event where the state has been set is the Load event - Event subscription should occur before the
PageLoadComplete
or they will not be raised
Consider the following description from MSDN
If controls are created dynamically at run time or declaratively within templates of data-bound controls, their events are initially not synchronized with those of other controls on the page. For example, for a control that is added at run time, the Init and Load events might occur much later in the page life cycle than the same events for controls created declaratively. Therefore, from the time that they are instantiated, dynamically added controls and controls in templates raise their events one after the other until they have caught up to the event during which it was added to the Controls collection.
The above is not so clear to me, but I have found the following. The following TextBox
's are created at design time
protected void Page_PreInit(object sender, EventArgs e)
{
this.txtDesignTextBox1.Text = "From PreInit";
this.txtDesignTextBox1.Text += DateTime.Now.ToString();
}
protected void Page_Init(object sender, EventArgs e)
{
this.txtDesignTextBox2.Text = "From Init";
this.txtDesignTextBox2.Text += DateTime.Now.ToString();
}
protected void Page_Load(object sender, EventArgs e)
{
this.txtDesignTextBox3.Text = "From Load";
this.txtDesignTextBox3.Text += DateTime.Now.ToString();
}
At first sight you might think that in every post all the textboxes are updated with the current date, but this is not the case, since they were created at design time they follow strictly the ASP.Net page life-cycle which means, their state is overriden after the PreInit and Init events, only the txtDesignTextBox3
is updated in every post because its Text
property is updated after the view state has been set (in the Load
event).
But with dynamic controls the behavior is different, remember the MSDN description:
for a control that is added at run time, the Init and Load events might occur much later in the page life cycle
Consider the following:
protected void Page_PreInit(object sender, EventArgs e)
{
var textBox = new TextBox { Text = "From PreInit", Width = new Unit("100%") };
textBox.Text += DateTime.Now.ToString();
this.myPlaceHolder.Controls.Add(textBox);
}
protected void Page_Init(object sender, EventArgs e)
{
var textBox = new TextBox { Text = "From Init", Width = new Unit("100%") };
textBox.Text += DateTime.Now.ToString();
this.myPlaceHolder.Controls.Add(textBox);
}
protected void Page_Load(object sender, EventArgs e)
{
var textBox = new TextBox { Text = "From Load", Width = new Unit("100%") };
textBox.Text += DateTime.Now.ToString();
this.myPlaceHolder.Controls.Add(textBox);
}
In this case, the controls behave slightly different, in this case, in each post, the controls are never updated not even the controls created in the Load
event
The reason is their life-cycle events occurs much later in the page-life cycle which means their state is overridden even after the Load event
To solve this, you can use the LoadComplete
event, in this event you can change the state of dynamic controls:
protected void Page_LoadComplete(object sender, EventArgs e)
{
var textBox = new TextBox { Text = "From LoadComplete", Width = new Unit("100%") };
textBox.Text += DateTime.Now.ToString();
this.myPlaceHolder.Controls.Add(textBox);
}
In this case, the state will be updated in each post.
However, take in consideration that you should subscribe to dynamic controls events, before the LoadComplete
event or they will not be raised.
... I know I hate this kind of behavior, that's why I love MVC
As a quick reference for controls created at design time: Notice how the LoadViewState
method is called after the PreInit
and Init
events but before the Load
event. The Load
event is considered stable because in this event you can access the view state of your controls. Also notice that the RaisePostBackEvent
method represent the control event that caused the post back, this can be, the SelectedIndexChanged
, Click
, etc this event is handled after the Load
event
For a complete detailed specification read the MSDN Page Life-Cycle documentation
SelectedIndexChange event not firing on dynamically created dropdownlist
I solved this issue by changing from an ASP dropdownlist to a regular SELECT input control and the event bound properly and the code now runs properly. This was a conversion to eliminate postback refreshes, so I really didn't need the ASP dropdownlist. I am still really curious as to why the event wouldn't bind properly, but the problem is now solved. I wanted to post this in case anyone else has a similar problem. Thanks for everyone's help!
Dynamically created Dropdownlist inside Gridview doesnot fire event on second time
For this you need to take and bind the dropdownlist again in Page_PreInit page method.
For Example....
protected void Page_PreInit(object sender, EventArgs e)
{
// here you need to build the gridview again.
// then the state will retain same......
}
asp:DropdownList not firing for SelectedIndexChanged event
I could not get the asp:DropdownList to fire the SelectedIndexChanged event. So this is how I completed the task.
Adding the dropdown dynamically as shown above and adding the change event that calls a javascript:
onchange='UpdateLocationList()'
This function had to be put in a .js file. This web site had a .js file already. It also had some AJAX calls that I used to complete the task.
In the UpdateLocationList(), I get the ID of the service type that was set as a value attribute in the dropdown. Then I use a function that is already part of the .js file to the LocationDetails page using the Service Type ID to display only the facilities of that service type. This is the function:
function updateLocationList() {
var ddlFacilityType = document.getElementById("FacilityTypeDDL");
var facilityValue = ddlFacilityType.options[ddlFacilityType.selectedIndex].value;
processAjax("/editor/Locations.aspx?Location_ID=" + facilityValue, "navPanel");
}
Works like a charm.
Thanks for all of your help.
Dynamically created sub-classed dropdownlist not firing event
Appears that your are developing a composite control - the correct way to go about this is to inherit from CompositeControl class and override CreateChildControls to add your child controls. This method is called by ASP.NET early in life-cycle and that would eliminate your view-state related issues.
See this article for developing composite control. For event, string typed property is not going to work - you must define the event at your composite control level. You can bubble up the child's event by raising your own event in the handler (this is shown in the article). Another way would be short-circuit the event handlers. For example, define the event in your composite control such as
public event EventHandler SelectedIndexChanged
{
add
{
childDdl.SelectedIndexChanged += value;
}
remove
{
childDdl.SelectedIndexChanged -= value;
}
}
childDll
is reference to your child ddl control.
Related Topics
Generic C# Code and the Plus Operator
How Does One Extract Each Folder Name from a Path
Converting ASP.NET MVC Razor @Helper Function into a Method of a Helper Class
Horizontal Scroll for Stackpanel Doesn't Work
If Strings Are Immutable in .Net, Then Why Does Substring Take O(N) Time
Apply Function to All Elements of Collection Through Linq
Deciding on When to Use Xmldocument VS Xmlreader
Dependency Injection VS Service Location
Proxy Basic Authentication in C#: Http 407 Error
How to Change Iis Express Port for a Site
Redirecting Output to the Text File C#
Func Delegate with Ref Variable
Generate 16-Bit Grayscale Bitmapdata and Save to File
An Error Occurred During Report Processing. -Rldc Reporting in ASP.NET MVC
How to Create a Message Box with "Yes", "No" Choices and a Dialogresult
Visual Studio 2015 Broken Razor Intellisense
Why Use Asqueryable() Instead of List()
Having the Output of a Console Application in Visual Studio Instead of the Console