ItemCommand not firing on first click in Repeater or GridView

前端 未结 3 733
无人及你
无人及你 2021-01-22 13:37

This has been driving me crazy for 2 days now - hope someone has seen this before.

I have this issue where the first click of a control within a repeater or grid view fa

相关标签:
3条回答
  • 2021-01-22 14:06

    I figured it out, but I don't understand why.
    The original code was:

    Me.rpAgreementContractors.DataSource = dtContractors
    Me.rpAgreementContractors.DataBind()
    Me.tblAgreementContractors.Visible = True
    Me.phDataPane.Controls.Add(Me.tblAgreementContractors)
    

    I changed it to make the table visible and add it to the placeholder before I set the datasource and bound it. Problem solved.

    Me.tblAgreementContractors.Visible = True
    Me.phDataPane.Controls.Add(Me.tblAgreementContractors)
    Me.rpAgreementContractors.DataSource = dtContractors
    Me.rpAgreementContractors.DataBind()
    
    0 讨论(0)
  • 2021-01-22 14:11

    MikeW,
    After hours and hours of fiddling with this, I found the root of your issue.
    It has nothing particular to do with the repeater or the gridview.
    It is simply a dynamic-controls-on-a-postback issue.

    To solve your issue:
    Amazingly, just one line is missing in your code.
    Right when you load the control, assign something to its ID, like so:

    UserControl uc = (UserControl)LoadControl(controlPath);
    uc.ID = "mycontrol";
    ph.Controls.Add(uc);
    

    That way, when you postback, the page knows which control is which.

    To explain this more easily, let's simplify the problem.
    Here's a scenario of clicking a button twice in a row that dynamically creates another button:

    • Make a single button, Button1, which when clicked will load another button dynamically, Button2. Assume Button2's action is as simple as displaying the current time.
    • Now, click Button1.
    • To retain Button2, you have to utilize ViewState to tell the page there's a dynamic control. Like you did, we can memorize the control's path, or the name of its class.
    • Right when the page posts back, in Page_Load, we look at the ViewState to see that there is a control we're trying to retain, so we load it right there (this is equivalent to your LoadUserControl() function above).
    • By now, Button2 is visible, and when clicked, it will do its action just fine.
    • Don't click Button2, just click Button1 again (which is equivalent to your case switching between two different dynamic controls).
    • Guess what happens now: Page_Load will load Button2 from the ViewState. And the Click event of Button1 will load ANOTHER Button2 instance, after clearing the placeholder.
    • Since you didn't assign it an ID, it will assign itself one in UniqueID, and those two Button2s will have something like ctl02 and ctl03
    • Now click Button2.
    • You would say "that's fine, we're overwriting the old one". Yes, but not without an ID.
    • Since you didn't give it an ID to identify it on the postback, it will utilize the UniqueID, which is sequentially generated.
    • Now the page is looking for ctl03, which doesn't exist, so the Click doesn't fire.
    • But, by now, we have a brand new Button2, with UniqueID ctl02.
    • Clicking this new Button2 will work just fine, coz on the postback, it's the only Button2, so it would coincidentally have a UniqueID of ctl02.

    So, how does assigning an ID make it work?
    That way, each new control generated will have the same ID, so on the postback, it can find what it's looking for, whether it was generated in Page_Load or on another button's Click event.

    Hope that explains why it works, but as far as you care, just assign it an ID and all will be good.
    I thought it would be interesting to share the mechanism behind it and why that's the case. =)

    0 讨论(0)
  • 2021-01-22 14:16

    I'm not sure about the rest of your code, but usually when I see a problem of "first action behaves different than subsequent actions" like this is because I placed something in the wrong side of the IsPostBack section.

    For example, I find myself binding when it's a postback, so my events don't work until the second postback, coz the first postback is when they were born, and the initial page load never did that part.

    I think you're on the right track; make sure you're binding and wiring up your events at the right moment.

    0 讨论(0)
提交回复
热议问题