ItemCommand not firing on first click in Repeater or GridView

前端 未结 3 736
无人及你
无人及你 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: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. =)

提交回复
热议问题