Динамический обработчик событий не запускается
Я хочу создать количество элементов управления динамически на основе числа, которое пользователь вводит в текстовое поле. Эта часть у меня работает нормально, но мне также нужно, чтобы динамически создаваемые текстовые поля имели собственные обработчики событий, чтобы пользователь мог вводить число в них и создавать больше элементов управления.
Моя проблема в том, что обработчик событий, который я настроил для этих элементов управления, не запускается. Возможно, я неправильно понимаю жизненный цикл страницы 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