动态事件处理程序未触发 [英] Dynamic Event Handler not Firing

查看:122
本文介绍了动态事件处理程序未触发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想根据用户在文本框中输入的数字来动态创建一定数量的控件.这部分工作正常,但我还需要动态创建的文本框来拥有自己的事件处理程序,以便用户可以在其中输入数字并创建更多控件.

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.

我的问题是,我为这些控件设置的事件处理程序不会触发.也许我没有正确理解ASP.NET页面的生命周期,但是我目前正在在OnInit事件内部生成动态控件(在我在第一个文本框的TextChanged事件内部生成动态控件之前,但是切换为使用OnInit基于Oded的建议的事件,我在这里找到:动态添加的事件处理程序未触发 ).

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).

编辑

我删除了最初发布的代码,否则发布太长了.

I removed the code I originally posted, because this post would just be too long otherwise.

我将在此发布我的整个.aspx代码以及其背后的代码,所以你们知道这正是我正在查看的内容.同样,此代码中生成的动态TextBox在其中更改文本时不会触发绑定到它的事件处理程序,而是会消失.有趣的是-我认为更改文本时确实会发生回发,但不会触发事件处理程序...

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前端:

<%@ 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>

代码隐藏:

局部类_Default 继承System.Web.UI.Page

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

尝试使用此代码创建自己的项目,看看是否遇到与我相同的问题-动态创建的TextBox回发了,但不触发其事件处理程序,然后TextBox从页面消失了……谢谢再次向您寻求帮助!

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!

推荐答案

由于ViewState

基本上:您正在添加动态控件以响应TextChanged事件,该事件在InitLoad之后以及反序列化ViewState之后触发.因此,您遇到了问题,因为ViewState不了解动态控件,并且与您的期望不同步.通过在Load阶段检查txtEnter.Text的值并在其中创建控件,您可以使ViewState知道控件(记住,该控件是在每次页面加载时创建的!),因此您的dynamicEventHandler现在具有要从中执行的上下文.

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.

以下是经过更正的代码(但为简单起见,作为带有嵌入式VB的单个文件,您当然可以将其分离为一个代码隐藏文件):

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>

这是Msft关于动态控件的起点,它解释了该行为.那里有很多资源.

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

专业提示:如果可以帮助,请不要使用动态控件.尽管可以说这是支持不使用JavaScript的浏览器的一种不错的方法,但是如今,首选的方法是使用JavaScript动态构建控件并使用AJAX进行更新.否则,您发送的数据将超出您的需要.使用PostBack时,每次您回发到服务器时(1)将整个ViewState PLUS表单数据上传到服务器,(2)重建整个页面(解析ViewState,呈现HTML)等等),以及(3)将所有HTML(和ViewState)发送回客户端.这对于使用功率和数据计划费率的移动设备尤其麻烦.

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.

这篇关于动态事件处理程序未触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆