Addhandler, button.click не срабатывает с использованием VB.NET

У меня проблема с кнопками и AddHandler. Это работает, только если я использую AddHandler Button1.click, AddressOf... в Page_load, но если я создаю кнопку динамически в одной из подпрограмм, событие не срабатывает.

Например,

<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
<asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="True">
    <asp:ListItem>1</asp:ListItem>
    <asp:ListItem>2</asp:ListItem>
</asp:DropDownList>
<asp:ScriptManager id="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:UpdatePanel id="UpdatePanel1" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="False">
    <contenttemplate>
        <asp:PlaceHolder id="PlaceHolder1" runat="server"></asp:PlaceHolder>
     </contenttemplate>
</asp:UpdatePanel>
<asp:UpdatePanel id="UpdatePanel2" runat="server" UpdateMode="Conditional">
    <contenttemplate>
        <asp:Label id="Label2" runat="server" Text="Label"></asp:Label>
    </contenttemplate>
</asp:UpdatePanel>


Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
    Label1.Text = Date.Now
    ScriptManager1.RegisterAsyncPostBackControl(DropDownList1)
End Sub

Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)
    Label2.Text = "Panel refreshed at " + Date.Now.ToString()
End Sub

Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DropDownList1.SelectedIndexChanged
    Dim b As New Button
    b.Text = "Click"
    ScriptManager1.RegisterAsyncPostBackControl(b)
    AddHandler b.Click, AddressOf Button1_Click
    PlaceHolder1.Controls.Add(b)
    UpdatePanel1.Update()
End Sub

Выпадающий список работает, а кнопка нет. Что я делаю неправильно?


person user649904    schedule 08.03.2011    source источник


Ответы (2)


Вы должны регенерировать ваши динамически созданные элементы управления при каждой обратной передаче (по крайней мере, в Page_Load, лучше в Page_Init). Вы должны установить идентификатор элементов управления соответствующим образом, поскольку он нужен ASP.Net для определения элемента управления, вызвавшего обратную передачу, и для обработки соответствующих событий.

Вы можете сохранить количество созданных кнопок в ViewState и использовать это для их повторного создания на Page_Load. Увеличивайте число при добавлении новой кнопки. Используйте этот номер также, чтобы сделать идентификатор кнопки уникальным (добавьте его к идентификатору), чтобы убедиться, что он одинаков при каждой обратной передаче.

Для получения дополнительной информации см. жизненный цикл страницы и ViewState с динамически добавляемыми элементами управления.

Редактировать: как прокомментировал Джоэл, если вам нужна только одна кнопка, вы можете установить ее идентификатор статически, но вам нужно повторно сгенерировать ее при обратной передаче, например. для обработки события click.

person Tim Schmelter    schedule 08.03.2011
comment
+1 - В этом случае, поскольку нет итерации для создания динамического элемента управления, идентификатор может быть установлен статически. - person Joel Etherton; 08.03.2011
comment
Спасибо за ваши ответы, но как мне отслеживать кнопки (более одной, это был просто фиктивный пример), которые я создаю? Я имею в виду, я знаю, что мне нужно использовать ViewState, но я не могу передать кнопку для сериализации, и я не знаю, какие идентификаторы я должен им дать. Другой вопрос, отладка кода, похоже, что код в DropDownList1_SelectedIndexChanged выполняется после Page_Load даже в ответ на событие SelectedIndexChanged. спасибо еще раз - person user649904; 10.03.2011
comment
@ user649904: как я уже упоминал выше, сохраняйте количество уже созданных кнопок в переменной int-ViewState-Variable (например, ButtonCount) и увеличивайте ее всякий раз, когда вы создаете новую. В page-init вы должны воссоздать все кнопки (от 1 до ButtonCount) и добавить их в свой заполнитель. Убедитесь, что идентификатор содержит индекс кнопки (ButtonCount при ее создании), поэтому они получают один и тот же идентификатор при каждой обратной передаче. - person Tim Schmelter; 10.03.2011
comment
Вау, ты быстрый! :) Я динамически создаю HtmlTable, и мне нужно добавлять кнопки в определенные строки всякий раз, когда необходимо изменить информацию, содержащуюся в других ячейках этой строки. Как я могу это сделать? - person user649904; 10.03.2011
comment
@ user649904: для меня это звучит так, как будто вы должны создать другой вопрос из этого или, по крайней мере, отредактировать этот вопрос и предоставить дополнительную информацию/исходный код, потому что я не буду (и не могу) отвечать на него здесь, в комментариях;) я бы предложить создать новый с другой темой. - person Tim Schmelter; 10.03.2011

Просто, чтобы помочь любому, у кого есть эта проблема и не совсем уверен, как реализовать. Вот быстрый пример. Этот пример начинается с отображения раскрывающегося списка. Когда пользователь выбирает что-то из раскрывающегося списка, появляется другой раскрывающийся список. Я набрал это с головы, так что это МОЖЕТ содержать ошибки, но вы поняли =)

В файле aspx добавьте заполнитель:

И в вашем коде: ...

Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init

    'Store control count in viewstate
    If Not IsPostBack Then ViewState("ControlCounter") = 1

    'Rebuild dynamic controls on every postback so when page's life cycle hits Page_Load, 
    'selected values in the viewstate (asp.net default behavior) can be loaded into the dropdowns
    Build_Dynamic_Controls()
End Sub

Protected Sub Build_Dynamic_Controls()

    'Clear placeholder
    myPlaceholder.Controls.Clear()

    'This is where the control counter stored in the viewstate comes into play
    For i as Integer = 0 To CInt(ViewState("ControlCounter") -1
        Dim ddlDynamic as New DropDownList With {
            .ID = "ddlDynamicDropdown" & i,
            .AutoPostBack = True
            }
        'This is the event that will be executed when the user changes a value on the form
        'and the postback occurs
        AddHandler ddlDynamic.SelectedIndexChanged, AddressOf ddlDynamic_SelectedIndexChanged

        'Add control to the placeholder
        myPlaceholder.Controls.Add(ddl)         

        'Put some values into the dropdown
        ddlDynamic.Items.Add("Value1")
        ddlDynamic.Items.Add("Value2")
        ddlDynamic.Items.Add("Value3")

    Next i
End Sub

Protected Sub ddlDynamic_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
    'When a dropdown value is changed, a postback is triggered (autopostback=true)
    'The event is captured here and we add another dropdown.

    'First we up the control count:
    ViewState("ControlCounter") = CInt(ViewState("ControlCounter")) + 1

    'Now that the "total controls counter" is upped by one, 
    'Let's recreate the controls in the placeholder to include the new dropdown
    Build_Dynamic_Controls()
End Sub

...

person Losbear    schedule 20.10.2011