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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 15:37:56  来源:igfitidea点击:

Dynamic Event Handler not Firing

asp.netvb.netevent-handlingpage-lifecycledynamic-controls

提问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事件,触发后InitLoad之后的ViewState被反序列化。因此,您遇到了问题,因为它ViewState不知道动态控件并且与您的期望不同步。通过检查的值txtEnter.TextLoad阶段和创建控件在那里,你可以让你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