locked
Dynamically added button click event fire only once! RRS feed

  • Question

  • User-1986993521 posted

    Hi

    Well, it may seem a repetitious and old problem, but I could not find any solution to it. I am writing a web application which has many forms all working fine with AJAX, except one. This form has two query panels and two parts for adding and editing items. One query panel is for searching through existing items and the other is for helping add/edit process. The entire form ASP.NET code is:

    <%@ Page Title="" Language="vb" AutoEventWireup="false" MasterPageFile="~/Masters/Forms.Master" CodeBehind="EditBrands.aspx.vb" Inherits="PharmaManageWeb.EditBrands" %>
    <asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
    	<title>ویرایش برندها</title>
    </asp:Content>
    <asp:Content ID="Content2" ContentPlaceHolderID="PageContent" runat="server">
    	<asp:ScriptManagerProxy runat="server" ID="PageScriptsProxy">
    	</asp:ScriptManagerProxy>
    	<asp:Table runat="server" CssClass="formtable">
    		<asp:TableRow runat="server">
    			<asp:TableCell runat="server">
    				<asp:UpdatePanel runat="server" ID="AddPanel" UpdateMode="Conditional">
    					<ContentTemplate>
    						<asp:Table runat="server" ID="AddTable" CssClass="formtable">
    							<asp:TableRow runat="server">
    								<asp:TableCell runat="server" ColumnSpan="2">
    									افزودن برند:
    								</asp:TableCell>
    							</asp:TableRow>
    							<asp:TableRow runat="server">
    								<asp:TableCell runat="server">
    									نام:
    								</asp:TableCell>
    								<asp:TableCell runat="server">
    									<asp:TextBox runat="server" ID="AddName" CssClass="rtlinput" Width="250px"></asp:TextBox>
    								</asp:TableCell>
    							</asp:TableRow>
    							<asp:TableRow runat="server">
    								<asp:TableCell runat="server">
    									کد ژنریک:
    								</asp:TableCell>
    								<asp:TableCell runat="server">
    									<asp:TextBox runat="server" ID="AddCode" CssClass="ltrinput" Width="100px"></asp:TextBox>
    								</asp:TableCell>
    							</asp:TableRow>
    							<asp:TableRow runat="server">
    								<asp:TableCell runat="server">
    									نام ژنریک:
    								</asp:TableCell>
    								<asp:TableCell runat="server">
    									<asp:TextBox runat="server" ID="AddGName" CssClass="ltrinput" Width="250px" Enabled="false"></asp:TextBox>
    								</asp:TableCell>
    							</asp:TableRow>
    							<asp:TableRow runat="server">
    								<asp:TableCell runat="server">&nbsp;</asp:TableCell>
    								<asp:TableCell runat="server">
    									<asp:Label runat="server" ID="AddErrMsg" ForeColor="Red"></asp:Label>
    								</asp:TableCell>
    							</asp:TableRow>
    							<asp:TableRow runat="server">
    								<asp:TableCell runat="server">&nbsp;</asp:TableCell>
    								<asp:TableCell runat="server" CssClass="buttoncell">
    									<asp:Button runat="server" ID="SubmitAdd" Text="ارسال" OnClick="DoAdd" />
    								</asp:TableCell>
    							</asp:TableRow>
    						</asp:Table>
    					</ContentTemplate>
    				</asp:UpdatePanel>
    				<br />
    				<asp:UpdatePanel runat="server" ID="EditPanel" UpdateMode="Conditional">
    					<Triggers>
    						<asp:AsyncPostBackTrigger ControlID="SubmitAdd" EventName="Click" />
    					</Triggers>
    					<ContentTemplate>
    						<asp:Table runat="server" ID="EditTable" CssClass="formtable">
    							<asp:TableRow runat="server">
    								<asp:TableCell runat="server" ColumnSpan="2">
    									ویرایش برند:
    								</asp:TableCell>
    							</asp:TableRow>
    							<asp:TableRow runat="server">
    								<asp:TableCell runat="server">
    									نام:
    								</asp:TableCell>
    								<asp:TableCell runat="server">
    									<asp:TextBox runat="server" ID="EditName" CssClass="rtlinput" Width="250px"></asp:TextBox>
    								</asp:TableCell>
    							</asp:TableRow>
    							<asp:TableRow runat="server">
    								<asp:TableCell runat="server">
    									کد ژنریک:
    								</asp:TableCell>
    								<asp:TableCell runat="server">
    									<asp:TextBox runat="server" ID="EditCode" CssClass="ltrinput" Width="100px"></asp:TextBox>
    								</asp:TableCell>
    							</asp:TableRow>
    							<asp:TableRow runat="server">
    								<asp:TableCell runat="server">
    									نام ژنریک:
    								</asp:TableCell>
    								<asp:TableCell runat="server">
    									<asp:TextBox runat="server" ID="EditGName" CssClass="ltrinput" Width="250px" Enabled="false"></asp:TextBox>
    								</asp:TableCell>
    							</asp:TableRow>
    							<asp:TableRow runat="server">
    								<asp:TableCell runat="server">&nbsp;</asp:TableCell>
    								<asp:TableCell runat="server">
    									<asp:Label runat="server" ID="EditErrMsg" ForeColor="Red"></asp:Label>
    								</asp:TableCell>
    							</asp:TableRow>
    							<asp:TableRow runat="server">
    								<asp:TableCell runat="server">&nbsp;</asp:TableCell>
    								<asp:TableCell runat="server" CssClass="buttoncell">
    									<asp:Button runat="server" ID="SubmitEdit" Text="ارسال" OnClick="DoEdit" Enabled="false" />
    								</asp:TableCell>
    							</asp:TableRow>
    						</asp:Table>
    					</ContentTemplate>
    				</asp:UpdatePanel>
    				<br />
    				<asp:UpdatePanel runat="server" ID="QueryPanel" UpdateMode="Conditional">
    					<ContentTemplate>
    						<asp:Table runat="server" ID="QueryTable" CssClass="formtable">
    							<asp:TableRow runat="server">
    								<asp:TableCell runat="server" ColumnSpan="3">
    									جستجوی برندها:
    								</asp:TableCell>
    							</asp:TableRow>
    							<asp:TableRow runat="server">
    								<asp:TableCell runat="server" Width="20px">
    									نام:
    								</asp:TableCell>
    								<asp:TableCell runat="server" Width="150px">
    									<asp:TextBox runat="server" ID="QueryName" CssClass="rtlinput" Width="250px"></asp:TextBox>
    								</asp:TableCell>
    								<asp:TableCell runat="server" CssClass="buttoncell">
    									<asp:Button runat="server" ID="SubmitQuery" Text="ارسال" OnClick="DoQuery" />
    								</asp:TableCell>
    							</asp:TableRow>
    							<asp:TableRow runat="server">
    								<asp:TableCell runat="server" ColumnSpan="3">
    									<asp:Label runat="server" ID="QueryErrMsg" ForeColor="Red"></asp:Label>
    								</asp:TableCell>
    							</asp:TableRow>
    							<asp:TableRow runat="server">
    								<asp:TableCell runat="server" ColumnSpan="3">
    									<asp:Table runat="server" ID="QueryResults" CssClass="resulttable">
    									</asp:Table>
    								</asp:TableCell>
    							</asp:TableRow>
    						</asp:Table>
    					</ContentTemplate>
    				</asp:UpdatePanel>
    			</asp:TableCell>
    			<asp:TableCell runat="server">
    				انتخاب کدهای ژنریک:<br />
    				<br />
    				<asp:UpdatePanel runat="server" ID="GQueryPanel" UpdateMode="Conditional">
    					<ContentTemplate>
    						<asp:Table runat="server" ID="GQueryTable" CssClass="formtable">
    							<asp:TableRow runat="server">
    								<asp:TableCell runat="server" ColumnSpan="3">
    								جستجوی کدها:
    								</asp:TableCell>
    							</asp:TableRow>
    							<asp:TableRow runat="server">
    								<asp:TableCell runat="server" Width="20px">
    								نام:
    								</asp:TableCell>
    								<asp:TableCell runat="server" Width="150px">
    									<asp:TextBox runat="server" ID="GQueryName" CssClass="ltrinput" Width="250px"></asp:TextBox>
    								</asp:TableCell>
    								<asp:TableCell runat="server" CssClass="buttoncell">
    									<asp:Button runat="server" ID="GSubmitQuery" Text="ارسال" OnClick="DoGQuery" />
    								</asp:TableCell>
    							</asp:TableRow>
    							<asp:TableRow runat="server">
    								<asp:TableCell runat="server" ColumnSpan="3">
    									<asp:Label runat="server" ID="GQueryErrMsg" ForeColor="Red"></asp:Label>
    								</asp:TableCell>
    							</asp:TableRow>
    							<asp:TableRow runat="server">
    								<asp:TableCell runat="server" ColumnSpan="3">
    									<asp:Table runat="server" ID="GQueryResults" CssClass="resulttable">
    									</asp:Table>
    								</asp:TableCell>
    							</asp:TableRow>
    						</asp:Table>
    					</ContentTemplate>
    				</asp:UpdatePanel>
    			</asp:TableCell>
    		</asp:TableRow>
    	</asp:Table>
    </asp:Content>
    

    And the code behind:

    Public Class EditBrands
        Inherits System.Web.UI.Page
    
    	Private Sub Re_CreateQueryResults(ByVal dbc As SqlConnection)
    		Dim qry As Base.Brands = Base.Brand.QueryBrands(dbc, Session("BrandQueryVal"))
    		Dim i As Integer
    		Dim tr As TableRow
    		Dim tc As TableCell
    		Dim bt As Button
    
    		QueryResults.Rows.Clear()
    		tr = New TableRow
    		tc = New TableCell
    		tc.Text = "شناسه"
    		tc.CssClass = "resulttableordercol"
    		tr.Cells.Add(tc)
    		tc = New TableCell
    		tc.Text = "نام"
    		tc.CssClass = "resulttabledatacol"
    		tr.Cells.Add(tc)
    		tc = New TableCell
    		tc.Text = "ویرایش"
    		tc.CssClass = "resulttableordercol"
    		tr.Cells.Add(tc)
    		QueryResults.Rows.Add(tr)
    		For i = 0 To qry.Count - 1
    			tr = New TableRow
    			tc = New TableCell
    			tc.Text = qry(i).ID
    			tc.CssClass = "resulttableordercol"
    			tr.Cells.Add(tc)
    			tc = New TableCell
    			tc.Text = qry(i).Name
    			tc.CssClass = "resulttabledatacol"
    			tr.Cells.Add(tc)
    			tc = New TableCell
    			bt = New Button
    			bt.Text = "ویرایش"
    			bt.ID = "SubmitEdit" & qry(i).ID
    			AddHandler bt.Click, AddressOf SubmitForEdit
    			tc.Controls.Add(bt)
    			tc.CssClass = "resulttableordercol"
    			tr.Cells.Add(tc)
    			QueryResults.Rows.Add(tr)
    		Next
    		If qry.Count = 0 Then
    			QueryErrMsg.Text = SystemSys.SysMan.GetSystemMessage(dbc, "NOTHINGFOUND")
    			QueryResults.Rows.Clear()
    		End If
    	End Sub
    
    	Private Sub Re_CreateGQueryResults(ByVal dbc As SqlConnection)
    		Dim qry As StatBookManager.GenericNames = StatBookManager.GenericName.QueryGenericNames(dbc, Session("GenericQueryVal3"))
    		Dim i As Integer
    		Dim tr As TableRow
    		Dim tc As TableCell
    		Dim bt As Button
    
    		GQueryResults.Rows.Clear()
    		tr = New TableRow
    		tc = New TableCell
    		tc.Text = "کد"
    		tc.CssClass = "resulttableordercol"
    		tr.Cells.Add(tc)
    		tc = New TableCell
    		tc.Text = "نام"
    		tc.CssClass = "resulttabledatacol"
    		tr.Cells.Add(tc)
    		tc = New TableCell
    		tc.Text = "انتخاب برای"
    		tc.ColumnSpan = 2
    		tc.CssClass = "resulttableordercol"
    		tr.Cells.Add(tc)
    		GQueryResults.Rows.Add(tr)
    		For i = 0 To qry.Count - 1
    			tr = New TableRow
    			tc = New TableCell
    			tc.Text = qry(i).Code
    			tc.CssClass = "resulttableordercol"
    			tr.Cells.Add(tc)
    			tc = New TableCell
    			tc.Text = qry(i).Name
    			tc.CssClass = "resulttabledatacolltr"
    			tr.Cells.Add(tc)
    			tc = New TableCell
    			bt = New Button
    			bt.Text = "افزودن"
    			bt.ID = "SubmitForAdd" & qry(i).ID
    			AddHandler bt.Click, AddressOf SubmitGForAdd
    			ScriptManager.GetCurrent(Me.Page).RegisterAsyncPostBackControl(bt)
    			tc.Controls.Add(bt)
    			tc.CssClass = "resulttableordercol"
    			tr.Cells.Add(tc)
    			tc = New TableCell
    			bt = New Button
    			bt.Text = "ویرایش"
    			bt.ID = "SubmitForEdit" & qry(i).ID
    			AddHandler bt.Click, AddressOf SubmitGForEdit
    			ScriptManager.GetCurrent(Me.Page).RegisterAsyncPostBackControl(bt)
    			tc.Controls.Add(bt)
    			tc.CssClass = "resulttableordercol"
    			tr.Cells.Add(tc)
    			GQueryResults.Rows.Add(tr)
    		Next
    		If qry.Count = 0 Then
    			GQueryErrMsg.Text = SystemSys.SysMan.GetSystemMessage(dbc, "NOTHINGFOUND")
    			GQueryResults.Rows.Clear()
    		Else
    			GQueryErrMsg.Text = ""
    		End If
    	End Sub
    
    	Protected Sub DoGQuery(ByVal sender As Object, ByVal e As EventArgs)
    		Dim dbc As SqlConnection = Connectivity.GetConnectionToDB(Session("DatabaseName"))
    
    		GQueryErrMsg.Text = ""
    		If GQueryName.Text.Trim = "" Then
    			GQueryErrMsg.Text = SystemSys.SysMan.GetSystemMessage(dbc, "NOGENERICNAME")
    			dbc.Close()
    			Exit Sub
    		End If
    
    		Session("GenericQueryVal3") = GQueryName.Text
    		Re_CreateGQueryResults(dbc)
    		dbc.Close()
    	End Sub
    
    	Protected Sub SubmitGForAdd(ByVal sender As Object, ByVal e As EventArgs)
    		MsgBox("A")
    		Dim dbc As SqlConnection = Connectivity.GetConnectionToDB(Session("DatabaseName"))
    		Dim itm As New StatBookManager.GenericName(dbc, Val(CType(sender, Button).ID.Substring(12)), StatBookManager.GenericName.IdentifyBy.ID)
    
    		AddCode.Text = itm.Code
    		AddGName.Text = itm.Name
    		AddPanel.Update()
    		dbc.Close()
    	End Sub
    
    	Protected Sub SubmitGForEdit(ByVal sender As Object, ByVal e As EventArgs)
    		MsgBox("E")
    		Dim dbc As SqlConnection = Connectivity.GetConnectionToDB(Session("DatabaseName"))
    		Dim itm As New StatBookManager.GenericName(dbc, Val(CType(sender, Button).ID.Substring(13)), StatBookManager.GenericName.IdentifyBy.ID)
    
    		EditCode.Text = itm.Code
    		EditGName.Text = itm.Name
    		EditPanel.Update()
    		dbc.Close()
    	End Sub
    
    	Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    		If Not Page.IsPostBack Then
    			If Session("GenericQueryVal3") IsNot Nothing Then
    				Session.Remove("GenericQueryVal3")
    				Exit Sub
    			End If
    		End If
    
    		Dim dbc As SqlConnection = Connectivity.GetConnectionToDB(Session("DatabaseName"))
    
    		If Page.IsPostBack AndAlso (Session("BrandQueryVal") IsNot Nothing) AndAlso (AJAXUtils.GetAsyncPostBackControlID(Me.Page, Request).EndsWith("$QueryPanel")) Then
    			Re_CreateQueryResults(dbc)
    			If QueryName.Text = "" Then QueryName.Text = Session("BrandQueryVal")
    		End If
    		If Page.IsPostBack AndAlso (Session("GenericQueryVal3") IsNot Nothing) AndAlso (AJAXUtils.GetAsyncPostBackControlID(Me.Page, Request).EndsWith("$GQueryPanel")) Then
    			Re_CreateGQueryResults(dbc)
    			If GQueryName.Text = "" Then GQueryName.Text = Session("GenericQueryVal3")
    		End If
    		dbc.Close()
    	End Sub
    
    	Protected Sub DoAdd(ByVal sender As Object, ByVal e As EventArgs)
    		Dim dbc As SqlConnection = Connectivity.GetConnectionToDB(Session("DatabaseName"))
    
    		AddErrMsg.Text = ""
    		If AddName.Text.Trim = "" Then
    			AddErrMsg.Text = SystemSys.SysMan.GetSystemMessage(dbc, "NOBRANDNAME")
    			dbc.Close()
    			Exit Sub
    		End If
    		If AddCode.Text.Trim = "" Then
    			AddErrMsg.Text = SystemSys.SysMan.GetSystemMessage(dbc, "NOGENERICCODE")
    			dbc.Close()
    			Exit Sub
    		End If
    
    		Dim itm As New Base.Brand
    
    		If Not itm.GenericName.Load(dbc, Val(AddCode.Text), StatBookManager.GenericName.IdentifyBy.Code) Then
    			AddErrMsg.Text = SystemSys.SysMan.GetSystemMessage(dbc, "GENERICNOTFOUND")
    			dbc.Close()
    			Exit Sub
    		End If
    
    		itm.Name = AddName.Text
    		itm.Register(dbc)
    		AddName.Text = ""
    		AddCode.Text = ""
    		AddGName.Text = ""
    		EditName.Text = ""
    		EditCode.Text = ""
    		EditGName.Text = ""
    		SubmitEdit.Enabled = False
    		dbc.Close()
    	End Sub
    
    	Protected Sub DoEdit(ByVal sender As Object, ByVal e As EventArgs)
    		Dim dbc As SqlConnection = Connectivity.GetConnectionToDB(Session("DatabaseName"))
    		Dim itm As New Base.Brand(dbc, Session("BrandEditID"))
    
    		EditErrMsg.Text = ""
    		If EditName.Text.Trim = "" Then
    			EditErrMsg.Text = SystemSys.SysMan.GetSystemMessage(dbc, "NOBRANDNAME")
    			dbc.Close()
    			Exit Sub
    		End If
    		If EditCode.Text.Trim = "" Then
    			EditErrMsg.Text = SystemSys.SysMan.GetSystemMessage(dbc, "NOGENERICCODE")
    			dbc.Close()
    			Exit Sub
    		End If
    		If Not itm.GenericName.Load(dbc, Val(EditCode.Text), StatBookManager.GenericName.IdentifyBy.Code) Then
    			EditErrMsg.Text = SystemSys.SysMan.GetSystemMessage(dbc, "GENERICNOTFOUND")
    			dbc.Close()
    			Exit Sub
    		End If
    
    		itm.Name = EditName.Text
    		itm.Save(dbc)
    		EditName.Text = ""
    		EditCode.Text = ""
    		EditGName.Text = ""
    		SubmitEdit.Enabled = False
    		Re_CreateQueryResults(dbc)
    		QueryPanel.Update()
    		dbc.Close()
    	End Sub
    
    	Protected Sub DoQuery(ByVal sender As Object, ByVal e As EventArgs)
    		Dim dbc As SqlConnection = Connectivity.GetConnectionToDB(Session("DatabaseName"))
    
    		QueryErrMsg.Text = ""
    		If QueryName.Text.Trim = "" Then
    			QueryErrMsg.Text = SystemSys.SysMan.GetSystemMessage(dbc, "NOBRANDNAME")
    			dbc.Close()
    			Exit Sub
    		End If
    
    		Session("BrandQueryVal") = QueryName.Text
    		Re_CreateQueryResults(dbc)
    		dbc.Close()
    	End Sub
    
    	Protected Sub SubmitForEdit(ByVal sender As Object, ByVal e As EventArgs)
    		Dim dbc As SqlConnection = Connectivity.GetConnectionToDB(Session("DatabaseName"))
    		Dim itm As New Base.Brand(dbc, Val(CType(sender, Button).ID.Substring(10)))
    
    		Session("BrandEditID") = itm.ID
    		EditName.Text = itm.Name
    		EditCode.Text = itm.GenericName.Code
    		EditGName.Text = itm.GenericName.Name
    		SubmitEdit.Enabled = True
    		EditPanel.Update()
    		Re_CreateQueryResults(dbc)
    		dbc.Close()
    	End Sub
    
    	Private Sub EditBrands_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
    		If Page.IsPostBack AndAlso (Session("GenericQueryVal3") IsNot Nothing) Then
    			Dim dbc As SqlConnection = Connectivity.GetConnectionToDB(Session("DatabaseName"))
    
    			Re_CreateGQueryResults(dbc)
    			dbc.Close()
    		End If
    	End Sub
    End Class

    Dynamic add/edit buttons are added in Re_CreateGQueryResults() subroutine. As you see, I have added two MsgBox statements saying "A" when a dynamic add button is clicked, and "E" when a dynamic edit button is clicked. The problem is exactly here: when I click on a dynamic add button, MsgBox("A") works, but only for the first! Further clicks don't result in any further message boxes (and not in any change in contents of AddName, AddCode, AddGName), and other dynamic edit buttons don't work as well until session expiration (say, with a rebuild on ASP.NET Development Server). A similar behavior happens with first click on dynamic edit buttons (No further message boxes, neither by edit buttons nor add buttons).

    Where is the problem?!

    Thanks in advance.

    Saturday, August 16, 2014 12:55 AM

All replies

  • User1918509225 posted

    Hi ubuntu118,

    Thanks for your post here.

    The cause of your problem is that the control is added dynamically on databind and you have to databind the gridview for each postback, the control being "clicked" is different each time.

    The event doesn't fire because at the time it needs to fire it doesn't exist as it did in the last iteration of the page.

    I suggest that you can place your button into a template ,so it exists properly.

    Best Regards,

    Kevin Shen.

    Sunday, August 17, 2014 10:46 PM
  • User-1986993521 posted

    Hi Kevin

    Thanks for your reply. Some points:

    1. I have other multi-part forms with similar structure which have no problem. All dynamic controls are re-added during every postback so that they exist whenever and wherever needed (I'm not new to AJAX and I know that all dynamically added controls vanish on every postback and I need to re-add them in order to capture events).
    2. I have no gridview control on my page! I wonder how could you find one in the above code! As a result, there is no need to databind controls because as you see, I put data in controls manually through my specially-defined classes and subroutines.
    3. I have recently found that when I click dynamically added buttons, even Page.Load event doesn't fire, meaning that client-side clicks don't cause postbacks at all! I wonder why?!

    Regards

    Sunday, August 17, 2014 11:55 PM
  • User-1986993521 posted

    Hi Chetan

    Thanks for your reply. I read those two links and all other links inside them. My scenario is not even a bit similar to any of them. The only thing I could test, was moving Page.Load event code to Page.Init event, which didn't change anything (although similar codes in Page.Load work fine in other pages in this application. The only difference is that similar tables contain only one column of buttons, but this one conatins two). Please keep in mind that first button clicks work, but not more. This means that there is no problem in registering events and handlers on poastback (because if there is any problem, even first clicks shouldn't work, as I have already seen). I am adding buttons to a table, not directly to UpdatePanel or anything else. Because buttons are inside the UpdatePanel which should handle their clicks, no AyncPostbackTrigger registration is required (as I have already tested with no success). Using UpdatePanel.Update() has no effect because of the same reason. Databinding didn't help too.

    Regards.

    Monday, August 18, 2014 1:05 AM
  • User-1986993521 posted

    OK

    I solved this problem by both moving page load code to page init event and adding AsyncPostBackTriggers for every dynamic add and edit button to GQueryPanel's Triggers collection (Although Microsoft explicitly says that this wouldn't work; but worked for me!). Now, there is another problem: SubmitGForAdd() and SubmitGForEdit() subroutines don't work as expected. Before this, on first click, AddCode and AddGName textboxes were taking their values and these values were displaying on browser. But now, they are always empty. I tested if code runs and itm variable loads it's data correctly. I believe these textboxes take their values, but they vanish on the way to browser! Can anyone explain why?!

    Thanks.

    Monday, August 18, 2014 7:00 AM