Under specific circumstances, ASP.NET fires the Change
event for an ASP.NET Web control even if you do not change the control.
↑ Back to the top
Some controls, such as the SelectedIndexChanged event in a DropDownList control or the TextChanged event in a TextBox control, rely on the registration of the Change event to use view
state. You encounter this problem when you create these controls dynamically
after the event is hooked up.
When ASP.NET renders the page to the
browser, the controls that are created dynamically do not have an associated
Change event. Because no event is present, ASP.NET does not save the view
state. This is called View State Optimization.
When the page is
posted back, and when the events are hooked up, ASP.NET expects view state but
finds that none exists. This difference fires the Change event even if the
control has not been changed.
↑ Back to the top
Make sure that you hook up the Change event for dynamically
created controls before ASP.NET renders the page. This ensures that view state
for the control exists.
↑ Back to the top
Steps to Reproduce the Behavior
Create the Web Form
- Create a new Visual Basic ASP.NET application named
ChangeFired.
- Open WebForm1 in designer mode. Drag a DataList control, a Button control, and a DataSet control onto the form.
- In the Add DataSet dialog box, click Untyped dataset, and then click OK. Keep the default names for all of the controls.
- Edit the Tables collection for DataSet1. Add a new table
named Table1.
- Edit the Columns collection for Table1. Add a new Column
named Column1.
- Click DataList1, and then change the DataSource property to DataSet1.
- Right-click DataList1, point to Edit Template, and then click Item Templates. Drag a DropDownList control to the ItemTemplate section.
- Click DropDownList1, and then add five items to the Items collection. Set the Text and the Value properties of these items to one,
two, three,
four, and five
respectively.
- Set the AutoPostBack property to true for DropDownList1.
- Edit the DataBindings collection for DropDownList1. Add the
following custom binding expression to the SelectedIndex property:
DataBinder.Eval(Container, "DataItem.Column1")
- Switch to HTML view. Set the trace attribute to true in the @ Page directive as follows:
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="WebForm1.aspx.vb"
Inherits="ChangeFired.WebForm1" trace="true" %>
Add the Code-Behind File
- Right-click WebForm1.aspx, and then click View Code.
- Add the following code to the Page_Load event:
DataSet1.Tables(0).Rows.Add(New Object() {"1"})
DataSet1.Tables(0).Rows.Add(New Object() {"2"})
DataSet1.Tables(0).Rows.Add(New Object() {"3"})
DataSet1.Tables(0).Rows.Add(New Object() {"4"})
If Not IsPostBack Then
DataBind()
End If
Dim objItem As DataListItem
For Each objItem In DataList1.Items
AddHandler CType(objItem.FindControl("DropDownList1"), _
DropDownList).SelectedIndexChanged, AddressOf DropDownList1_SelectedIndexChanged
If Not objItem.FindControl("DropDownList1") Is Nothing Then
Trace.Write("Added SelectedIndexChanged Handler")
End If
Next
- Create a new Sub procedure below the Page_Load event to handle the SelectedIndexChanged event as follows:
Private Sub DropDownList1_SelectedIndexChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs)
DataBind()
Trace.Write("SelectedIndexChanged, DataBind()")
'Uncomment the following code to resolve this problem.
'Dim objItem As DataListItem
'For Each objItem In DataList1.Items
' AddHandler CType(objItem.FindControl("DropDownList1"), _
' DropDownList).SelectedIndexChanged, AddressOf DropDownList1_SelectedIndexChanged
'Next
End Sub
Run the Sample
- Run the page. Notice that the dynamically created DropDownList controls contain view state in the trace information for the
Control tree.
This occurs because the call to the DataBind method dynamically creates the DropDownList controls, and you hook up the event handler after the DataBind call in the Page_Load event. Because the controls have an event handler, View State
Optimization does not take place. - Click the button on the page. Notice that a post back
occurs, and only the code inside the Page_Load event runs. View state exists for the DropDownList controls because an event handler is associated with the
control.
- Change the value in one of the DropDownList controls. Notice that a post back occurs. In addition, notice
that ASP.NET fires the Page_Load event and runs the DropDownList1_SelectedIndexChanged event.
- In the DropDownList1_SelectedIndexChanged event, call the DataBind method again to create new DropDownList controls.
Because the SelectedIndexChanged event is not hooked up to these new DropDownList controls, ASP.NET uses View State Optimization and does not save
the view state for the new DropDownList controls. - Review the trace information for the Control tree. Notice
that the DropDownList controls do not have view state.
- Click the button on the page. Notice that the post back
occurs, and notice that ASP.NET runs the Page_Load event. Because you hook the SelectedIndexChanged event to the DropDownList controls, ASP.NET expects view state to be associated with the
controls.
However, because view state does not exist, ASP.NET fires
the SelectedIndexChanged event, even though you do not select an item.
Resolution
To resolve this problem, uncomment the code in the
DropDownList1_SelectedIndexChanged event so that the event handlers hook up with the newly created
controls.
↑ Back to the top