Tech Off Thread

16 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

AddHandler MyButton.Click...Breaking an updatePanel?

Back to Forum: Tech Off
  • User profile image
    jsampsonPC

    First off, the AJAX controls for .NET are fantastic - I am absolutely head-over-heels in love with them. Unfortunately, I'm having a small problem.

    I have an UpdatePanel on my page, and it's working very well. I put a datagrid in there, ran asynch' commands to the server to remove data from a database, and the datagrid updates nicely with no post back.

    My next step was to build a list of data-objects representing values in a database upon page load. I want this list to exist within my updatePanel, and have linkbuttons that when clicked will make a call back to the server, remove their corresponding record, and watch as the update panel keeps me up-to-date.

    Here's how I have things laid out right now:

    Default.aspx:
    ...
    <asp:UpdatePanel id="MyPanel" runat="Server">
         <asp:Table id="myTable" runat="Server">
         </asp:Table>
    </asp:UpdatePanel>
    ...

    Default.aspx.vb:
    Protected Sub Page_Init(...)
         DrawTicket() ' Draws my list
    End Sub

    Protected Sub myButton_Click(...)
         ' This line removes a database record based
         ' upon the commandArgument of the sender

         DrawTicket() ' Draws my list
    End Sub

    Protected Sub DrawTicket()
         Make a New TableRow
         Make a New TableCell
         Make a new LinkButton

         Set The CommandArgument of linkButton
         Set The CommandName of linkButton

         ' This line kills my asynch post-backs, and forces
         ' Full page post backs

         AddHandler LinkButton.Click, AddressOf myButton_Click
        
         myTable.Rows.Add(TableRow)
    End Sub

  • User profile image
    NuTcAsE

    Add 

       ScriptManager1.RegisterAsyncPostBackControl(linkButton)

    for each link button in the DrawTicket function. That should enable the post backs of the link button to go through the script manager.

  • User profile image
    jsampsonPC

    NuTcAsE wrote:
    Add 

       ScriptManager1.RegisterAsyncPostBackControl(linkButton)

    for each link button in the DrawTicket function. That should enable the post backs of the link button to go through the script manager.


    Excellent, that fixed the async aspect of it. But it's still only responding to every-other click...

    It's so weird....I have two labels on my page too...one to show the last time the page was accessed, and one to show the last time the UpdatePanel updated....When I click a linkButton, and pass back a value to the server, it removes a record from the database, redraws the list of linkbuttons, and updates the label showing the updatepanel has been updated.

    But on every second click, it updates the time, but doesn't actually delete the corresponding record...This lifecycle is odd Smiley

  • User profile image
    NuTcAsE

    jsampsonPC wrote:
    

    Excellent, that fixed the async aspect of it. But it's still only responding to every-other click...

    It's so weird....I have two labels on my page too...one to show the last time the page was accessed, and one to show the last time the UpdatePanel updated....When I click a linkButton, and pass back a value to the server, it removes a record from the database, redraws the list of linkbuttons, and updates the label showing the updatepanel has been updated.

    But on every second click, it updates the time, but doesn't actually delete the corresponding record...This lifecycle is odd Smiley


    Could it be that when the table containing the list of linkbuttons is updated, after the first click, the command arguments are incorrect?

    It's hard to tell what the problem could be but the lifecycle with dynamic controls and UpdatePanel should be the same as dynamic controls in plain ASP.Net.

  • User profile image
    jsampsonPC

    Hmm, here's another thing I just noticed:
    When my page loads, I click a linkbutton, it responds by deleting the corresponding record from the database, and updating the updatepanel...then It comes to the where it will ignore my next demand..

    When I hover over a linkbutton now, it tells me "javascript:__doPostBack('ctl63','')", then I click it, and it doesn't respond, then I hover over it again and now the very same linkbutton says "javascript:__doPostBack('31','')"....I am not sure yet why the value is changing...It's almost as if an incorrect value is being placed on there after a successful command is executed, and then when I try to click a linkbutton with an incorrect value, the page fixes itself, showing me the true value, and then allows me to do a successful postback.

  • User profile image
    jsampsonPC

    I think you're right, after a successful command has been ran, it's messing up my commandArguments some how - I'm going to take a moment and look further into this.

  • User profile image
    NuTcAsE

    jsampsonPC wrote:
    Hmm, here's another thing I just noticed:
    When my page loads, I click a linkbutton, it responds by deleting the corresponding record from the database, and updating the updatepanel...then It comes to the where it will ignore my next demand..

    When I hover over a linkbutton now, it tells me "javascript:__doPostBack('ctl63','')", then I click it, and it doesn't respond, then I hover over it again and now the very same linkbutton says "javascript:__doPostBack('31','')"....I am not sure yet why the value is changing...It's almost as if an incorrect value is being placed on there after a successful command is executed, and then when I try to click a linkbutton with an incorrect value, the page fixes itself, showing me the true value, and then allows me to do a successful postback.


    Do you mind posting your source code? You can strip out the database stuff. I'm guessing that somewhere during that first click its almost as if the click event's postback event reference is being replaced.

  • User profile image
    jsampsonPC

    Sure, give me one second to gather it and clean it up a bit for public-viewing. Here's some numbers I recorded after a few click-events:

    Page Loads:

    LnkBtn 1667         ctl03
    LnkBtn 1668         ctl05
    LnkBtn 1669         ctl07
    LnkBtn 1670         ctl09

    Click to delete 1667, successfully deleted:

    Page Is PostedBack

    LnkBtn 1668         ctl23
    LnkBtn 1669         ctl25
    LnkBtn 1670         ctl27

    Click to delete 1668, failed but UpdatePanel updates:

    LnkBtn 1668         ctl03
    LnkBtn 1669         ctl05
    LnkBtn 1670         ctl07

    Click to delete 1668, successfully deleted:

    Those are the linkButtons, and their corresponding value in the doPostBack() function call on the client.

  • User profile image
    jsampsonPC

    Default.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>

            <asp:Label ID="timeLabel" runat="server"></asp:Label>

            <asp:ScriptManager ID="mySM" runat="server"></asp:ScriptManager>

            <asp:UpdatePanel ID="myUP" runat="server">

                <ContentTemplate>

                    <asp:Label ID="myLabel" runat="server"></asp:Label>

                    <asp:Label ID="tableLabel" runat="server"></asp:Label>

                    <asp:TextBox ID="webSVtext" runat="server"></asp:TextBox>

                    <asp:Table ID="userTicket" runat="server"></asp:Table>

                    <asp:GridView ID="myLittleGrid" runat="server"></asp:GridView>

                </ContentTemplate>

            </asp:UpdatePanel>

        </div>

        </form>

        <script type="text/javascript">

       

        </script>

    </body>

    </html>

     

    Default.aspx.vb

     

    Imports System.Web.Configuration.WebConfigurationManager

     

    Partial Class _Default

        Inherits System.Web.UI.Page

     

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

            Dim myButton As New LinkButton

            myButton.ID = "myButton"

            myButton.Text = "Step 2/3 Button"

            AddHandler myButton.Click, AddressOf myButton_Click

            myUP.ContentTemplateContainer.Controls.Add(myButton)

            DrawTicket()

            DrawGrid()

        End Sub

     

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

            timeLabel.Text = DateTime.Now.ToString()

            myLabel.Text = DateTime.Now.ToString()

        End Sub

     

        Protected Sub myButton_Click(ByVal sender As Object, ByVal e As System.EventArgs)

            Dim myService As New GetNumberOfProductsInOrder

     

            'webSVtext.Text = myService.RemoveOption(webSVtext.Text).ToString()

            webSVtext.Text = myService.RemoveOption(CType(sender, LinkButton).CommandArgument).ToString()

     

            DrawGrid()

            DrawTicket()

        End Sub

     

        Protected Sub DrawGrid()

            Dim myConn As New SqlConnection("...")

            Dim myComm As New SqlCommand("sp_DoSomething")

            myComm.CommandType = CommandType.StoredProcedure

            Dim myAdap As New SqlDataAdapter(myComm)

            Dim myDS As New DataTable

            myComm.Connection = myConn

     

            Try

                myConn.Open()

                myAdap.Fill(myDS)

     

                myLittleGrid.DataSource = myDS

                myLittleGrid.DataBind()

            Catch ex As Exception

                Page.Title = ex.Message()

            Finally

                myConn.Close()

            End Try

        End Sub

     

        Protected Sub DrawTicket()

     

            userTicket.Rows.Clear()

     

            ' Create a database connection

            Dim myConn As New SqlConnection("...")

            Dim myComm As New SqlCommand("sp_GetStuff")

            myComm.CommandType = CommandType.StoredProcedure

            myComm.Connection = myConn

            Dim myReader As SqlDataReader

     

            Try

                myConn.Open()

                myReader = myComm.ExecuteReader()

                While myReader.Read()

                    Dim myRow As New TableRow

                    Dim mycell1 As New TableCell

                    Dim mycell2 As New TableCell

                    Dim myButton As New LinkButton

                    myButton.Text = myReader("StandingOptionID").ToString()

                    myButton.CommandArgument = myReader("StandingOptionID").ToString()

                    AddHandler myButton.Click, AddressOf myButton_Click

                    mySM.RegisterAsyncPostBackControl(myButton)

                    Dim myLabel As New Label

                    myLabel.Text = myReader("ProductTitle").ToString()

                    mycell1.Controls.Add(myButton)

                    mycell2.Controls.Add(myLabel)

                    myRow.Cells.Add(mycell1)

                    myRow.Cells.Add(mycell2)

                    userTicket.Rows.Add(myRow)

                End While

            Catch ex As SqlException

                tableLabel.Text = ex.Message()

            Finally

                myConn.Close()

            End Try

     

        End Sub

    End Class

     

     

  • User profile image
    NuTcAsE

    jsampsonPC wrote:
    

       snip..source code



    I think I figured out why its not responding on the second click. Heres what happens;

    when the page is created for the first time it creates the rows and link buttons and starts assigning them ClientID values based on control sequence, so lest say those link buttons are assigned ctl01, ctl02, ctl03.

    When the link button is clicked, the page init starts again and re-creates the linkbutton (DrawTicket()) and assigned them ControlID's ctl01, ctl02, ctl03. Then the click event handler launches removes the ticket and then re-draws the link buttons. Heres where it starts to get screwey...  when the link buttons are re-created they are assigned ControlID's ctl04, ctl05 because ctl01, ctl02, ctl03 were previously created (even though the table.Rows.Clear() function is called.)

    So now on the second click, the page_init calls DrawTable() and re-creates the linkButtons, but this time they are assigned ctl01, ctl02. But the request param __EVENTTARGET contains 'ctl04' which doesnt exist so the click event is not fired and the page is redrawn... now with the right ID's.

  • User profile image
    jsampsonPC

    So to test that I should not find a button with a ctl-value lower than the highest number found on an initial page load. What I mean is, if I load the page, and I have ctl03 - ctl10, and I delete 03, on the postback I should have only controls with an id greater than ctl10?

    I'll check to see how these work...

    Any suggestions if this is indeed the case?

  • User profile image
    jsampsonPC

    I think you're absolutely right...the ctl-numbers never overlap. On the successful load, they are low numbers, starting at about 3, and going to about 11. On the postback, which is the unsuccessful load, they are all high numbers, starting at about 1 over the upper-bound of the previous page-load. It looks just as you suggested.

  • User profile image
    NuTcAsE

    jsampsonPC wrote:
    So to test that I should not find a button with a ctl-value lower than the highest number found on an initial page load. What I mean is, if I load the page, and I have ctl03 - ctl10, and I delete 03, on the postback I should have only controls with an id greater than ctl10?

    I'll check to see how these work...

    Any suggestions if this is indeed the case?


    Give the link buttons explicit ID values. For example, in each While (reader.Rad()) set the mybutton.ID = "deleteTicketButton" + reader.GetInt32(0).ToString (assuming reader.GetInt32(0) is some unique identifier).

    That way the ClientID generated for the link buttons will not follow the dynamic control ID assignment that ASP.Net does for dynamic controls.

    [Edit: Spelling and grammer... some days...grrr]

  • User profile image
    NuTcAsE

    NuTcAsE wrote:
    
    jsampsonPC wrote:
    So to test that I should not find a button with a ctl-value lower than the highest number found on an initial page load. What I mean is, if I load the page, and I have ctl03 - ctl10, and I delete 03, on the postback I should have only controls with an id greater than ctl10?

    I'll check to see how these work...

    Any suggestions if this is indeed the case?


    Give the link buttons explicit ID values. For example, in each While (reader.Rad()) set the mybutton.ID = "deleteTicketButton" + reader.GetInt32(0).ToString (assuming reader.GetInt32(0) is some unique identifier).

    That way the ClientID generated for the link buttons will not follow the dynamic control ID assignment that ASP.Net does for dynamic controls.

    [Edit: Spelling and grammer... some days...grrr]


    Also another suggestion. Dont use the Click event of the LinkButtons, instead register a event handler for Command. In the Click event hander you will always have to type cast the sender to the LinkButton to get the CommandArgument value, while in the Command event handler its there in the event args.

  • User profile image
    jsampsonPC

    NuTcAsE wrote:
    ...Give the link buttons explicit ID values...


    That works! Dang, I wish the solution would have been more complex Sad Thanks, NutCase.

  • User profile image
    NuTcAsE

    jsampsonPC wrote:
    
    NuTcAsE wrote:
    ...Give the link buttons explicit ID values...


    That works! Dang, I wish the solution would have been more complex Sad Thanks, NutCase.


    Awesome!

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.