Dynamically Added Dropdownlists Are Not Firing Selectedindexchanged Event

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 the Init 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 or Init events, their states will be automatically set in a post event, which means in the LoadComplete 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

Sample Image

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



Leave a reply



Submit