vb.net 动态事件处理程序未触发
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19598141/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Dynamic Event Handler not Firing
提问by Nate Major
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).
我的问题是我为这些控件设置的事件处理程序没有触发。也许我没有正确理解 ASP.NET 页面生命周期,但我目前正在 OnInit 事件中生成动态控件(在我在第一个文本框的 TextChanged 事件中生成它们之前,但切换到使用 OnInit基于 Oded 建议的事件我在这里找到:动态添加的事件处理程序未触发)。
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 代码和后面的代码,所以你们知道这正是我正在看的。同样,由此代码生成的动态 TextBox,当其中的文本发生更改时,不会触发绑定到它的事件处理程序,它只会消失。有趣的是 - 我认为当您更改文本时确实会发生回发,但它不会触发事件处理程序......
ASPX front end:
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>
CODE BEHIND:
背后的代码:
Partial Class _Default Inherits System.Web.UI.Page
部分类_默认继承 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!
尝试使用此代码制作您自己的项目,看看您是否遇到与我相同的问题 - 动态创建的 TextBox 回发,但不触发其事件处理程序,然后 TextBox 从页面中消失...再次感谢您帮助!
采纳答案by nothingisnecessary
Dynamic controls can be a bit tricky because of ViewState
动态控件可能有点棘手,因为 ViewState
Basically: you were adding the dynamic controls in response to the TextChangedevent, which fires after Initand Loadand after the ViewStatewas deserialized. Therefore you were experiencing the problem because the ViewStatewas not aware of the dynamic controls and was out of sync with your expectations. By checking the value of txtEnter.Textin the Loadphase and creating the controls there, you can make your ViewStateaware of the controls (which, remember, are created EVERY time the page loads!), and therefore your dynamicEventHandlernow has a context from which to execute.
基本上是:你在应对加入动态控件TextChanged事件,触发后Init和Load之后的ViewState被反序列化。因此,您遇到了问题,因为它ViewState不知道动态控件并且与您的期望不同步。通过检查的值txtEnter.Text的Load阶段和创建控件在那里,你可以让你ViewState知道的控件(其中,记住,创建每次页面加载!),所以你dynamicEventHandler现在已经从执行上下文。
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):
这是更正后的代码(但为了简单起见,作为带有嵌入式 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>
Here is a starting point from Msft about dynamic controls that explains the behavior. There are a lot of resources out there for this.
这是 Msft 关于解释行为的动态控件的起点。有很多资源可以做到这一点。
http://msdn.microsoft.com/en-us/library/hbdfdyh7.aspx
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 ViewStatePLUS 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.
专业提示:如果可以,请不要使用动态控件。虽然这可以说是支持不使用 JavaScript 的浏览器的一种不错的方式,但现在首选的方法是使用 JavaScript 动态构建控件并使用 AJAX 进行更新。否则,您发送的数据将超出您的需要。当您使用 时PostBack,每次您 POST 回服务器时,您都是 (1) 将整个ViewStatePLUS 表单数据上传到服务器,(2) 在服务器上重建整个页面(解析ViewState、呈现 HTML 等),以及(3) 将所有 HTML(和)发送ViewState回客户端。这对于应用电源使用和数据计划费率的移动设备来说尤其麻烦。
回答by ajakblackgoat
You will need to set the AutoPostbackproperty of the dynamic textboxes to Truefor them to fire their TextChanged event.
您需要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

