我想根据用户输入文本框的数字动态创建一定数量的控件。这部分我工作正常,但我还需要动态创建的文本框来拥有自己的事件处理程序,因此用户可以在其中输入数字,并创建更多控件。
我的问题是我为这些控件设置的事件处理程序不会触发。也许我没有正确理解ASP.NET页面生命周期,但我目前正在OnInit事件中生成动态控件(在我在第一个文本框的TextChanged事件中生成它们之前,但切换到使用OnInit根据Oded的建议我在这里找到的事件:Dynamically Added Event Handler Not Firing)。
修改
我删除了我最初发布的代码,因为这篇文章的篇幅太长了。
我将发布我的整个.aspx代码和这里的代码,所以你们知道这正是我正在看的。同样,当文本在其中更改时,由此代码生成的动态TextBox不会触发绑定到它的事件处理程序,它只会消失。有趣的是 - 我认为当您更改文本时实际上会发生回发,但它不会触发事件处理程序......
ASPX前端:
<%@ 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>
背后的代码:
Partial Class _Default 继承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
尝试使用此代码制作您自己的项目,看看您是否遇到了同样的问题 - 动态创建的TextBox回发,但不会触发其事件处理程序,然后TextBox从页面中消失...感谢你再次寻求帮助!
答案 0 :(得分:3)
由于ViewState
基本上:您正在添加动态控件以响应TextChanged
事件,该事件在Init
和Load
之后以及ViewState
反序列化后触发。因此,您遇到了问题,因为ViewState
不了解动态控件并且与您的期望不一致。通过检查txtEnter.Text
阶段中Load
的值并在其中创建控件,您可以让ViewState
了解控件(记住,每次页面加载时都会创建控件! ),因此您的dynamicEventHandler
现在有一个上下文来执行。
这是更正后的代码(但为了简单起见,作为带有嵌入式VB的单个文件,您当然可以将其分离为代码隐藏文件):
<%@ 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>
以下是Msft关于动态控件的起点,它解释了行为。这里有很多资源。
http://msdn.microsoft.com/en-us/library/hbdfdyh7.aspx
专家提示:如果可以提供帮助,请不要使用动态控件。虽然这可以说是一种支持不使用JavaScript的浏览器的好方法,但现在首选的方法是使用JavaScript动态构建控件并使用AJAX进行更新。否则,您发送的数据超出了您的需要。当您使用PostBack
时,每次回到服务器时,您都会(1)将整个ViewState
PLUS表格数据上传到服务器,(2)重建整个页面(解析{{ 1}},在服务器上呈现HTML等,以及(3)将所有HTML(和ViewState
)发送回客户端。对于适用电源和数据计划费率的移动设备而言,这尤其麻烦。
答案 1 :(得分:1)
您需要将动态文本框的AutoPostback
属性设置为True
,以便它们触发TextChanged事件。
Protected Overrides Sub OnInit(ByVal e As System.EventArgs)
MyBase.OnInit(e)
For i As Int16 = 0 To 5
Dim txtTest As New TextBox
txtTest.Text = "this is an OnInit generated textbox"
txtTest.ID = "testOnInit" + i.ToString
txtTest.AutoPostBack = True
Form.Controls.Add(txtTest)
AddHandler txtTest.TextChanged, AddressOf txtTest_TextChanged
Next
End Sub
Protected Sub txtTest_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs)
Dim txt As TextBox = DirectCast(sender, TextBox)
lblTest.Text = txt.ID & " value changed to " & txt.Text
End Sub