ItemCommand Fires Before ItemDataBound on PostBack? WTH?

2.6k views Asked by At

This is just stupid. I've been at this for over 5 hours and can't figure out why my freaking commands aren't firing properly. The only ones that fire properly are the Built-in commands "Edit" & "Cancel"

Markup

<asp:ListView ID="NewProduct" runat="server" DataSourceID="NewProductSDS" DataKeyNames="ID">
    <ItemTemplate>
        <div>
            <asp:LinkButton ID="accept" runat="server" CommandName="Accept" />
            <asp:LinkButton ID="edit" runat="server" CommandName="Edit" />
            <asp:LinkButton ID="delete" runat="server" CommandName="Reject" />
            <%# Eval("Product")%>
        </div>
    </ItemTemplate>
    <EditItemTemplate>
        <div>
            <asp:LinkButton ID="accept" runat="server" CommandName="Accept" />
            <asp:LinkButton ID="cancel" runat="server" CommandName="Cancel" />
            <asp:TextBox ID="NewProductName_tb" runat="server"></asp:TextBox>
        </div>
    </EditItemTemplate>
</asp:ListView>
<asp:SqlDataSource ID="NewProductSDS" runat="server"
    ConnectionString="<%$ ConnectionStrings:myConnectionString %>"
    SelectCommand="select ID, Product from Products">
</asp:SqlDataSource>

Codebehind

Protected Sub ItemBind(ByVal sender As Object, ByVal e As ListViewItemEventArgs) Handles NewProduct.ItemDataBound
    If e.Item.ItemType = ListViewItemType.DataItem Then
        sender.DataKeys(e.Item.DataItemIndex).Value.ToString() 'get the datakey
        'Display each key as it's created for troubleshooting.
        Label1.Text += "bound: " + sender.DataKeys(e.Item.DataItemIndex).Value.ToString() + "<br />"
    End If
End Sub
Protected Sub ItemClick(ByVal sender As Object, ByVal e As CommandEventArgs) Handles NewProduct.ItemCommand
    'Check if an event fired when a LinkButton is clicked.
    Label1.Text = "Command Event Fired"
    If e.CommandName = "Accept" Then
        Session.Add("PKey", sender.DataKeys(e.CommandArgument).Value.ToString)
        Label1.Text = "Accept key " + Session.Item("PKey")
    ElseIf e.CommandName = "Reject" Then
        Session.Add("PKey", sender.DataKeys(e.CommandArgument).Value.ToString)
        Label1.Text = "Reject key " + Session.Item("PKey")
    End If
End Sub

That's all the code I'm using to try to debug this garbage. The weirdest thing that I can't figure out is that all the keys display on a fresh page load like so...

bound: 9
bound: 12
bound: 27
bound: 31
bound: 32

Then suddenly when I click a built-in Command (Edit or Cancel in this case, notice they are not in my ItemCommand event handler code) this garbage shows up, implying to me that it's seeing the click before binding.

Command Event Firedbound: 9
bound: 12
bound: 27
bound: 31
bound: 32

Whatever the heck is going on, the problem that I'm trying to solve is that my custom Commands are not being recognized for some reason. Any ideas? I've searched high and low for answers and nothing :(

If you copied all this code into a new project it should compile. I would be EVER so grateful for your help. --- I'm getting so desperate I'm about to bind to handle every freaking event for the ListView control in hopes of revealing something about the firing order and perhaps get an idea what's going wrong. --- :'(

UPDATE: I did it lol. Interesting, but not sure it tells me anything new. Here's what fires on a fresh page load with all events bound:

Init
Load
DataBinding
ItemCreated
bound: 9
ItemCreated
bound: 12
ItemCreated
bound: 27
ItemCreated
bound: 31
ItemCreated
bound: 32
DataBound
PreRender
1

There are 1 answers

6
competent_tech On BEST ANSWER

I believe that the order of events (ItemClick then ItemDataBound) is the correct order of processing. The ItemClick is fired from the client, then, before the page is sent back to the user, ItemDataBound is fired.

I would suggest trying to add specific OnClick events to each of your custom buttons to see if they fire.

Update:

I suspect that you may also be encountering exceptions within the ItemClick event. If you move the setting of the label above the Session manipulation, you may see the label being updated with your custom code.

You should wrap the body of the event in an exception handler and step through in debug to see what exception is being fired.

You would probably also be better served by casting some of the properties you are working with to their native types. For example:

Dim theListView As ListView

theListView = DirectCast(sender, ListView)

Dim theDataItem As ListViewDataItem

theDataItem = DirectCast(e.Item, ListViewDataItem)

If e.CommandName = "Accept" Then
    Label1.Text = "Accept key " + Session.Item("PKey")
    Session.Add("PKey", theListView.DataKeys(theDataItem.DisplayIndex).Value.ToString)
ElseIf e.CommandName = "Reject" Then
    Label1.Text = "Reject key " + Session.Item("PKey")
    Session.Add("PKey", theListView.DataKeys(theDataItem.DisplayIndex).Value.ToString)
End If