I want to create an amount of controls dynamically based on a number the user enters into a textbox. This part I have working fine, but I also need the dynamically created textboxes to have event handlers of their own, so the user can enter a number into them, and have more controls created.
My problem is that the event handler I've setup for these controls to use does not fire. Maybe I'm not understanding the ASP.NET page life cycle correctly, but I am currently having the dynamic controls generated inside the OnInit event (before I was generating them inside the TextChanged event of the very first textbox, but switched to using the OnInit event based on advice from Oded I found here: Dynamically Added Event Handler Not Firing).
EDIT
I removed the code I originally posted, because this post would just be too long otherwise.
I'm going to post my entire .aspx code and the code behind here, so you guys know this is exactly what I'm looking at. Again, the dynamic TextBox that gets generated by this code, when text is changed inside it, does not fire the event handler that is bound to it, and it simply disappears. Interesting to note – I think a postback actually does occur when you change the text, but it doesn't fire the event handler…
ASPX front end:
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div id="dynamicControlDiv">
<asp:Label ID="lblEnter" runat="server" Text="Enter the amount of textboxes you want:"></asp:Label>
<asp:TextBox ID="txtEnter" runat="server" AutoPostBack="true"></asp:TextBox>
<asp:Label ID="lblConfirm" runat="server" Text=""></asp:Label>
</div>
</form>
</body>
</html>
CODE BEHIND:
Partial Class _Default
Inherits System.Web.UI.Page
Dim numOfDesiredControls As Int16
Protected Sub txtEnter_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtEnter.TextChanged
Try
numOfDesiredControls = Convert.ToInt16(txtEnter.Text)
If Not numOfDesiredControls = 0 Then
For i As Int16 = 1 To numOfDesiredControls
Dim txtTest As New TextBox
txtTest.Text = "dynamicTextBox"
txtTest.ID = "dynamicTextBox" + i.ToString
txtTest.AutoPostBack = True
Form.Controls.Add(txtTest)
AddHandler txtTest.TextChanged, AddressOf dynamicEventHandler
Next
End If
Catch ex As Exception
End Try
End Sub
Protected Sub dynamicEventHandler(ByVal sender As Object, ByVal e As System.EventArgs)
' If the event handler gets fired, reflect this by changing the text of lblConfirm
lblConfirm.Visible = True
lblConfirm.Text = "Event handler fired!"
End Sub
End Class
Try making your own project with this code, and see if you get the same problems I am – the dynamically created TextBox posts back, but does not fire its event handler, and then the TextBox disappears from the page… Thank you again for the help!
Best Answer
Dynamic controls can be a bit tricky because of
ViewState
Basically: you were adding the dynamic controls in response to the
TextChanged
event, which fires afterInit
andLoad
and after theViewState
was deserialized. Therefore you were experiencing the problem because theViewState
was not aware of the dynamic controls and was out of sync with your expectations. By checking the value oftxtEnter.Text
in theLoad
phase and creating the controls there, you can make yourViewState
aware of the controls (which, remember, are created EVERY time the page loads!), and therefore yourdynamicEventHandler
now has a context from which to execute.Here is the corrected code (but as a single file with embedded VB for simplicity, you could of course separate this out into a codebehind file):
Here is a starting point from Msft about dynamic controls that explains the behavior. There are a lot of resources out there for this.
http://msdn.microsoft.com/en-us/library/hbdfdyh7.aspx
Pro-tip: don't use dynamic controls if you can help it. While this is arguably a decent way to support browsers that do not use JavaScript, these days the preferred approach is to build the controls dynamically with JavaScript and use AJAX to do updates. Otherwise, you are sending way more data than you need to. When you use
PostBack
, every time you you POST back to the server you are (1) uploading the entireViewState
PLUS the form data to the server, (2) rebuilding the entire page (parsingViewState
, rendering HTML, etc.) on the server, and (3) sending all the HTML (andViewState
) back to the client. This is especially troublesome for mobile devices where power usage and data plan rates apply.