Динамический обработчик событий не запускается

Я хочу создать количество элементов управления динамически на основе числа, которое пользователь вводит в текстовое поле. Эта часть у меня работает нормально, но мне также нужно, чтобы динамически создаваемые текстовые поля имели собственные обработчики событий, чтобы пользователь мог вводить число в них и создавать больше элементов управления.

Моя проблема в том, что обработчик событий, который я настроил для этих элементов управления, не запускается. Возможно, я неправильно понимаю жизненный цикл страницы ASP.NET, но в настоящее время у меня есть динамические элементы управления, сгенерированные внутри события OnInit (до того, как я сгенерировал их внутри события TextChanged самого первого текстового поля, но переключился на использование OnInit событие, основанное на совете от Одеда, я нашел здесь: динамически добавленный обработчик событий не срабатывает).

РЕДАКТИРОВАТЬ

Я удалил код, который я первоначально разместил, потому что иначе это сообщение было бы слишком длинным.

Я собираюсь опубликовать весь мой.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>

КОД позади:

Частичный класс _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 исчезает со страницы... Еще раз спасибо за помощь!

2 ответа

Решение

Динамическое управление может быть немного сложнее из-за 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 ПЛЮС данные формы на сервер, (2) перестраивание всей страницы (разбор ViewState, рендеринг HTML и т. д.) на сервере и (3) отправка всего HTML (и ViewState) вернуться к клиенту. Это особенно проблематично для мобильных устройств, где применяются показатели энергопотребления и тарифные планы.

Вам нужно будет установить 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
Другие вопросы по тегам