Search code examples
asp.netvb.netwebformsupdatepanel

ASPX Webform - Programmatically created linkbutton never trigger event in UpdatePanel


I have a simple test app with a MasterPage, a Default.aspx page containing an UpdatePanel with few html and asp controls.

My purpose is to create dynamically controls and bind events.

I know the issue about IDs on controls and binding event handlers, as the the fact that you need to register an asynccontrol to the scriptmanager.

I tried many things but my dynamically created linkbutton goes in PostBack, in the MasterPage on_load but NEVER in my attached click event.

Extra infos : the declarative asp button triggers its click event after Default.aspx Page_Load and performing a Postback, the LinkButton dynamically created goes as well in the Default Page_Load but never trigger btnTest_Click2. This app is on .NET 4.5 (Visual Studio 2015).

Any idea ?

Thx.

Default.aspx :

<%@ Page Title="Home Page" Language="VB" MasterPageFile="~/Site.Master" AutoEventWireup="false" CodeBehind="Default.aspx.vb" Inherits="TestUpdatePanel._Default" %>

<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
    <h1>This will never change !</h1>
    <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
        <ContentTemplate>
            <asp:Button runat="server" ID="btnTest" CssClass="btn btn-success" OnClick="btnTest_Click" Text="Hit me hard !" />
        <div runat="server" id="testDiv">
            <p>Hello this a test</p>
        </div>            
        </ContentTemplate>
        <Triggers>
        </Triggers>
    </asp:UpdatePanel>   

</asp:Content>

Default.aspx.vb code-behind :

Public Class _Default
    Inherits Page

    Dim currentsm As ScriptManager

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load

        currentsm = CType(Page.Master.FindControl("sm1"), ScriptManager)

        If Not IsPostBack Then
            MsgBox("It's not a postback", MsgBoxStyle.DefaultButton1)
        Else
            MsgBox("It's a Postback !", MsgBoxStyle.DefaultButton1)
        End If


    End Sub

    Protected Sub btnTest_Click(sender As Object, e As EventArgs)

        BuildButton()

    End Sub

    Private Sub BuildButton()

        Dim link = New LinkButton

        link.ID = "linkTest"
        link.ClientIDMode = ClientIDMode.Static
        link.Text = "This is a new Ajax link :-)"

        AddHandler link.Click, AddressOf btnTest_Click2

        Dim trigger As AsyncPostBackTrigger = New AsyncPostBackTrigger
        trigger.ControlID = link.ClientID
        trigger.EventName = "Click"
        UpdatePanel1.Triggers.Add(trigger)

        currentsm.RegisterAsyncPostBackControl(link)

        testDiv.Controls.Add(link)
        UpdatePanel1.Update()

    End Sub

    Private Sub BuildDiv()

        Dim divToCreate = New HtmlGenericControl

        divToCreate.TagName = "div"
        divToCreate.ID = "newDiv"
        divToCreate.ClientIDMode = ClientIDMode.Static
        divToCreate.Attributes("class") = ("btn btn-alert")
        divToCreate.InnerText = "It works !"

        testDiv.Controls.Add(divToCreate)

        UpdatePanel1.Update()

    End Sub


    Protected Sub btnTest_Click2(sender As Object, e As EventArgs)

        BuildDiv()

    End Sub

Solution

  • I finally got it with the use of the OnInit event to instanciate the dynamically created controls like this :

    Protected Overrides Sub OnInit(e As EventArgs)
        MyBase.OnInit(e)
        If IsPostBack Then
            currentsm = CType(Page.Master.FindControl("sm1"), ScriptManager)
            Dim sender = Request.Form("__EVENTTARGET").ToString
            If sender.Contains("btnTest") Then
                BuildButton()
            ElseIf sender.Contains("linkTest") Then
                BuildDiv()
            End If
        End If
    End Sub