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 after Init
and Load
and after the ViewState
was deserialized. Therefore you were experiencing the problem because the ViewState
was not aware of the dynamic controls and was out of sync with your expectations. By checking the value of txtEnter.Text
in the Load
phase and creating the controls there, you can make your ViewState
aware of the controls (which, remember, are created EVERY time the page loads!), and therefore your dynamicEventHandler
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):
<%@ Page Language="VB" AutoEventWireup="false" %>
<script runat="server">
Dim numOfDesiredControls As Int16
Protected Sub Page_Load() Handles form1.Load
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
' txtTest.EnableViewState = False
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
Dim txt As TextBox
txt = CType(sender, TextBox)
lblConfirm.Visible = True
lblConfirm.Text = "Event handler " + txt.Id + " fired: " + txt.Text ' append ID and text so we know which one fired it.
End Sub
</script>
<!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>
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 entire ViewState
PLUS the form data to the server, (2) rebuilding the entire page (parsing ViewState
, rendering HTML, etc.) on the server, and (3) sending all the HTML (and ViewState
) back to the client. This is especially troublesome for mobile devices where power usage and data plan rates apply.