Nested datagrids -- events not handled correctly

Discussion in 'ASP .Net Datagrid Control' started by Steve Hershoff, Aug 27, 2006.

  1. Hi everyone,

    I've got a strange one here. There are two datagrids on my page, one nested
    within the other. I'll refer to them as the topmost and secondary
    datagrids.

    In the topmost datagrid's OnItemDataBound() method we check for the row in
    which it's appropriate to add the secondary datagrid. Exactly one row in
    the topmost grid will contain the secondary grid.

    When we do find the appropriate row in the topmost grid, we add to one of
    its cells a DropDownList and then our secondary datagrid. Meanwhile, within
    this secondary datagrid we add a LinkButton to one of its cells, for
    specific rows. Not all rows of the secondary grid get a button. We use the
    ItemEvent() method to check.

    When we add the DropDownList and LinkButtons, we create event handlers for
    their SelectedIndexChanged() and Click() events, respectively. Now comes my
    problem.

    What's strange is that when I click on one of the LinkButtons the page is
    reloaded (as expected), but then the DropDownList's SelectedIndexChanged()
    handler is fired. I never touched the DropDownList however.

    What's more, if I fail to call the secondary datagrid's DataBind() method
    from within this DropDownList event handler, the LinkButton's Click()
    handler is never called-- even though that's the control I clicked on to
    start the chain of events!

    So I'm confused to say the least. I realize this stuff can be tricky and
    I'm not expecting a total answer to my problem, but does any of this ring a
    bell? Specifically, why is the DropDownList's event handler being fired
    when the LinkButton is clicked, and why is the LinkButton's Click() handler
    never called unless the DropDownList's event handler calls the secondary
    datagrid's BindData() method?

    Thanks very much.
     
    Steve Hershoff, Aug 27, 2006
    #1
    1. Advertising

  2. Steve Hershoff

    Tim_Mac Guest

    hi steve,

    here is a good article on this re-occuring question:
    http://odetocode.com/Blogs/scott/archive/2006/07/19/5365.aspx

    when you create a control programatically like you do in your code, you need
    to fully re-create it for each postback. otherwise your event is going to
    be raised for a control that doesn't exist, since each post back is its own
    separate entity. this is why the click event doesn't happen unless you
    re-bind the datagrid.

    strange that the SelectedIndexChanged event is fired, did you try debugging
    to see what the call stack is like when that event is triggered. this will
    help you track whether it is in response to some of your own code. can you
    post your code for databinding the drop down list?

    tim

    ------------------------------------------
    blog: http://tim.mackey.ie
    "Steve Hershoff" <> wrote in message
    news:...
    > Hi everyone,
    >
    > I've got a strange one here. There are two datagrids on my page, one
    > nested within the other. I'll refer to them as the topmost and secondary
    > datagrids.
    >
    > In the topmost datagrid's OnItemDataBound() method we check for the row in
    > which it's appropriate to add the secondary datagrid. Exactly one row in
    > the topmost grid will contain the secondary grid.
    >
    > When we do find the appropriate row in the topmost grid, we add to one of
    > its cells a DropDownList and then our secondary datagrid. Meanwhile,
    > within this secondary datagrid we add a LinkButton to one of its cells,
    > for specific rows. Not all rows of the secondary grid get a button. We
    > use the ItemEvent() method to check.
    >
    > When we add the DropDownList and LinkButtons, we create event handlers for
    > their SelectedIndexChanged() and Click() events, respectively. Now comes
    > my problem.
    >
    > What's strange is that when I click on one of the LinkButtons the page is
    > reloaded (as expected), but then the DropDownList's SelectedIndexChanged()
    > handler is fired. I never touched the DropDownList however.
    >
    > What's more, if I fail to call the secondary datagrid's DataBind() method
    > from within this DropDownList event handler, the LinkButton's Click()
    > handler is never called-- even though that's the control I clicked on to
    > start the chain of events!
    >
    > So I'm confused to say the least. I realize this stuff can be tricky and
    > I'm not expecting a total answer to my problem, but does any of this ring
    > a bell? Specifically, why is the DropDownList's event handler being fired
    > when the LinkButton is clicked, and why is the LinkButton's Click()
    > handler never called unless the DropDownList's event handler calls the
    > secondary datagrid's BindData() method?
    >
    > Thanks very much.
    >
     
    Tim_Mac, Aug 28, 2006
    #2
    1. Advertising

  3. Hi Tim,

    Thanks for your note, and for the links. When the SelectedIndexChanged
    event is fired it's the only element in the call stack, aside from the
    ubiquitious <Non User Code> portion below it.

    Here's the code used for creating the dropdown. It's called in the OnInit()
    method of the web control (this is all contained in an ascx file):

    this.ddl_Transaction_Filt = new DropDownList();
    this.ddl_Transaction_Filt.Items.Add(new ListItem("Taken", "TAKEN"));
    this.ddl_Transaction_Filt.Items.Add(new ListItem("Accrued", "ACCR"));
    this.ddl_Transaction_Filt.Items.Add(new ListItem("Adjusted", "ADJ"));
    this.ddl_Transaction_Filt.Items.Add(new ListItem("All", "ALL"));
    this.ddl_Transaction_Filt.CssClass = "Normal";
    this.ddl_Transaction_Filt.AutoPostBack = true;
    this.ddl_Transaction_Filt.SelectedIndexChanged += new
    System.EventHandler(this.ddl_Transaction_Filt_SelectedIndexChanged);

    ....as you can tell, the dropdown is hard-coded.

    Here's something interesting: later on in the OnInit() method I compare a
    session variable with the value in that dropdown list. If the session
    variable and the value in the dropdown differ I set the index in the
    dropdown appropriately.

    The guy who worked on this page before me made a mistake in the code and
    mixed up the "ADJ" and "ALL" bits. The result being the dropdown's index
    changes on every page load, which means the secondary datagrid is bound
    every page load, which also means (it appears) the LinkButton's click event
    is handled when needed. If I "fix" his code so the dropdown works correctly
    the LinkButton no longer works.



    "Tim_Mac" <> wrote in message
    news:...
    > hi steve,
    >
    > here is a good article on this re-occuring question:
    > http://odetocode.com/Blogs/scott/archive/2006/07/19/5365.aspx
    >
    > when you create a control programatically like you do in your code, you
    > need to fully re-create it for each postback. otherwise your event is
    > going to be raised for a control that doesn't exist, since each post back
    > is its own separate entity. this is why the click event doesn't happen
    > unless you re-bind the datagrid.
    >
    > strange that the SelectedIndexChanged event is fired, did you try
    > debugging to see what the call stack is like when that event is triggered.
    > this will help you track whether it is in response to some of your own
    > code. can you post your code for databinding the drop down list?
    >
    > tim
    >
    > ------------------------------------------
    > blog: http://tim.mackey.ie
    > "Steve Hershoff" <> wrote in message
    > news:...
    >> Hi everyone,
    >>
    >> I've got a strange one here. There are two datagrids on my page, one
    >> nested within the other. I'll refer to them as the topmost and secondary
    >> datagrids.
    >>
    >> In the topmost datagrid's OnItemDataBound() method we check for the row
    >> in which it's appropriate to add the secondary datagrid. Exactly one row
    >> in the topmost grid will contain the secondary grid.
    >>
    >> When we do find the appropriate row in the topmost grid, we add to one of
    >> its cells a DropDownList and then our secondary datagrid. Meanwhile,
    >> within this secondary datagrid we add a LinkButton to one of its cells,
    >> for specific rows. Not all rows of the secondary grid get a button. We
    >> use the ItemEvent() method to check.
    >>
    >> When we add the DropDownList and LinkButtons, we create event handlers
    >> for their SelectedIndexChanged() and Click() events, respectively. Now
    >> comes my problem.
    >>
    >> What's strange is that when I click on one of the LinkButtons the page is
    >> reloaded (as expected), but then the DropDownList's
    >> SelectedIndexChanged() handler is fired. I never touched the
    >> DropDownList however.
    >>
    >> What's more, if I fail to call the secondary datagrid's DataBind() method
    >> from within this DropDownList event handler, the LinkButton's Click()
    >> handler is never called-- even though that's the control I clicked on to
    >> start the chain of events!
    >>
    >> So I'm confused to say the least. I realize this stuff can be tricky and
    >> I'm not expecting a total answer to my problem, but does any of this ring
    >> a bell? Specifically, why is the DropDownList's event handler being
    >> fired when the LinkButton is clicked, and why is the LinkButton's Click()
    >> handler never called unless the DropDownList's event handler calls the
    >> secondary datagrid's BindData() method?
    >>
    >> Thanks very much.
    >>

    >
    >
     
    Steve Hershoff, Aug 28, 2006
    #3
  4. Steve Hershoff

    Tim_Mac Guest

    hi steve, i'm trying to piece together the setup there.

    so the drop-down-list SelectedIndexChanged event fires because of your code
    that compares the session variable and updates the SelectedIndex of the menu
    accordingly. that one is explained then?

    if you only bind the secondary datagrid in response to a
    SelectedIndexChanged event, then the LinkButton Click event won't fire for
    that datagrid. you need to bind the secondary datagrid for each post back
    where you want to use events with it (especially on the Postback that occurs
    when you click the LinkButton).

    you're code should look something like this:

    public void Page_Load(...)
    {
    if(!IsPostBack)
    {
    // bind the topmost datagrid and other first time load stuff
    }
    else
    {
    // bind the secondary datagrid, dropdownlist, extra button
    column, etc.
    // exactly as you had it as of the last postback
    }
    }

    this approach works for me. if this doesn't give you any ideas, can you
    post your Page_Load and OnInit code, and anything else that affects the
    loading/binding of the dynamic controls. if it's worth it, you may like to
    create a stripped down version of the page and i could test it out here.

    cheers.
    tim
     
    Tim_Mac, Aug 28, 2006
    #4
  5. Thanks again Tim. You understand how the dropdown list and the session
    variable interact.

    I guess I need to play around a little more. I suppose the way things work
    is that when I click the LinkButton a postback is generated, then the
    Page_Load is called. I assumed the LinkButton's Click() event handler would
    be called even if the datagrid it resides in isn't bound again, but it
    appears not?

    One more thing, if you don't mind another question. Would you happen to
    know what events are fired or what happens in general on a page when a
    DataBind takes place? I ask because in our Page_Load we're binding the
    topmost datagrid every time, whether IsPostBack is true or not.

    The first time we enter this page the topmost grid is bound only once. If I
    click on a hyperlink to "show the secondary datagrid," the Page_Load method
    is called again, with IsPostBack set to true. So far so good. Again,
    Page_Load binds the master datagrid.

    However, this time the page is immediately reloaded(?) (IsPostBack equals
    false now) and the master datagrid is bound yet again. Only now is the
    secondary datagrid loaded and bound.

    I don't understand why Page_Load is called twice in succession? I'm not
    reloading or redirecting back to the page, at least not directly in my code.
    Strange indeed.

    I keep trying to find good information on the page lifecycle. The
    4guysfromrolla.com site is great for workaday questions involving aspx, but
    it's still tough. No two sources seem to agree on what happens. Either
    that or they flood you with terms like PagePreRenderInit() and set your head
    spinning. Do you happen to have any favored websites or books that do a
    good job on this?

    Thanks again for all your help. I really appreciate it.

    -Steve.




    "Tim_Mac" <> wrote in message
    news:...
    > hi steve, i'm trying to piece together the setup there.
    >
    > so the drop-down-list SelectedIndexChanged event fires because of your
    > code that compares the session variable and updates the SelectedIndex of
    > the menu accordingly. that one is explained then?
    >
    > if you only bind the secondary datagrid in response to a
    > SelectedIndexChanged event, then the LinkButton Click event won't fire for
    > that datagrid. you need to bind the secondary datagrid for each post back
    > where you want to use events with it (especially on the Postback that
    > occurs when you click the LinkButton).
    >
    > you're code should look something like this:
    >
    > public void Page_Load(...)
    > {
    > if(!IsPostBack)
    > {
    > // bind the topmost datagrid and other first time load stuff
    > }
    > else
    > {
    > // bind the secondary datagrid, dropdownlist, extra button
    > column, etc.
    > // exactly as you had it as of the last postback
    > }
    > }
    >
    > this approach works for me. if this doesn't give you any ideas, can you
    > post your Page_Load and OnInit code, and anything else that affects the
    > loading/binding of the dynamic controls. if it's worth it, you may like
    > to create a stripped down version of the page and i could test it out
    > here.
    >
    > cheers.
    > tim
    >
     
    Steve Hershoff, Aug 29, 2006
    #5
  6. Steve Hershoff

    Tim_Mac Guest

    hi Steve,
    you're welcome, glad to help out.

    you only need to bind the topmost datagrid for the first postback. the
    reason for this is because it is a statically declared control in the aspx,
    and the viewstate is enough to maintain its state across postbacks.
    however, if you change the underlying data, i.e. run an update/delete SQL
    query, then you will need to re-bind the datagrid afterwards because the
    viewstate data will not reflect your data changes.

    the reason your events are getting lost for the secondary datagrid is
    because this control does not exist for any given postback unless it is
    programatically created exactly as it was previously. does that make sense?

    re: events for a DataBind()... i'm not aware of any knock-on events raised
    by calling DataBind on a control. if you set a breakpoint at the DataBind
    call, and hit F11 you will step into any user code that runs as a result of
    calling Databind.

    i know what you mean about the complexity of the Page lifecycle. i
    generally don't concern myself with such events, except obviously Page_Load.
    there is lots of opinion on where/when to create your dynamic controls.
    Personally i like to do it all in Page_Load because it is very clear then
    what is going on, you don't need to worry about the order of events.
    Page_Load will always run first, and then any events will fire after that.
    advanced users may say this is too simplistic, but i have done plenty of
    complex scenarios containing nested dynamic controls only using Page_Load.

    the official resource on the Page/Postback lifecycle is on MSDN2:
    http://msdn2.microsoft.com/en-us/library/ms178472.aspx
    this really is an excellent article and it is the one i was looking for
    earlier but couldn't find. well worth an afternoon of studying. they also
    give a few tips for nested databound controls under the heading "catch up
    events"

    i am stumped by the double Page_Load. i can't see how Page.Postback could
    be false unless you have some Response.Redirect code or some javascript to
    reload the page, or if your linkbutton doesn't directly cause a postback.
    i.e. if it is rendered as <a href="SamePage.aspx?Select=10">Select</a>

    can you post the aspx and code-behind? don't worry about the database
    connections etc, just by looking at the code it may be clear where the
    problem is.

    thanks
    tim

    "Steve Hershoff" <> wrote in message
    news:OnV$...
    > Thanks again Tim. You understand how the dropdown list and the session
    > variable interact.
    >
    > I guess I need to play around a little more. I suppose the way things
    > work is that when I click the LinkButton a postback is generated, then the
    > Page_Load is called. I assumed the LinkButton's Click() event handler
    > would be called even if the datagrid it resides in isn't bound again, but
    > it appears not?
    >
    > One more thing, if you don't mind another question. Would you happen to
    > know what events are fired or what happens in general on a page when a
    > DataBind takes place? I ask because in our Page_Load we're binding the
    > topmost datagrid every time, whether IsPostBack is true or not.
    >
    > The first time we enter this page the topmost grid is bound only once. If
    > I click on a hyperlink to "show the secondary datagrid," the Page_Load
    > method is called again, with IsPostBack set to true. So far so good.
    > Again, Page_Load binds the master datagrid.
    >
    > However, this time the page is immediately reloaded(?) (IsPostBack equals
    > false now) and the master datagrid is bound yet again. Only now is the
    > secondary datagrid loaded and bound.
    >
    > I don't understand why Page_Load is called twice in succession? I'm not
    > reloading or redirecting back to the page, at least not directly in my
    > code. Strange indeed.
    >
    > I keep trying to find good information on the page lifecycle. The
    > 4guysfromrolla.com site is great for workaday questions involving aspx,
    > but it's still tough. No two sources seem to agree on what happens.
    > Either that or they flood you with terms like PagePreRenderInit() and set
    > your head spinning. Do you happen to have any favored websites or books
    > that do a good job on this?
    >
    > Thanks again for all your help. I really appreciate it.
    >
    > -Steve.
    >
    >
    >
    >
    > "Tim_Mac" <> wrote in message
    > news:...
    >> hi steve, i'm trying to piece together the setup there.
    >>
    >> so the drop-down-list SelectedIndexChanged event fires because of your
    >> code that compares the session variable and updates the SelectedIndex of
    >> the menu accordingly. that one is explained then?
    >>
    >> if you only bind the secondary datagrid in response to a
    >> SelectedIndexChanged event, then the LinkButton Click event won't fire
    >> for that datagrid. you need to bind the secondary datagrid for each post
    >> back where you want to use events with it (especially on the Postback
    >> that occurs when you click the LinkButton).
    >>
    >> you're code should look something like this:
    >>
    >> public void Page_Load(...)
    >> {
    >> if(!IsPostBack)
    >> {
    >> // bind the topmost datagrid and other first time load stuff
    >> }
    >> else
    >> {
    >> // bind the secondary datagrid, dropdownlist, extra button
    >> column, etc.
    >> // exactly as you had it as of the last postback
    >> }
    >> }
    >>
    >> this approach works for me. if this doesn't give you any ideas, can you
    >> post your Page_Load and OnInit code, and anything else that affects the
    >> loading/binding of the dynamic controls. if it's worth it, you may like
    >> to create a stripped down version of the page and i could test it out
    >> here.
    >>
    >> cheers.
    >> tim
    >>

    >
    >
     
    Tim_Mac, Aug 29, 2006
    #6
  7. Good call on the double page_load, Tim. The "show secondary datagrid" link
    does indeed lead to a response.redirect, so that should explain things
    there. I'd be glad to post the code-behind info, but I think you've got me
    on the right direction.

    I'll definitely check out that MSDN2 link you posted on the page lifecycle.
    I've had it with guesswork on what gets fired and when!

    Indebted as always,

    -Steve

    "Tim_Mac" <> wrote in message
    news:...
    > hi Steve,
    > you're welcome, glad to help out.
    >
    > you only need to bind the topmost datagrid for the first postback. the
    > reason for this is because it is a statically declared control in the
    > aspx, and the viewstate is enough to maintain its state across postbacks.
    > however, if you change the underlying data, i.e. run an update/delete SQL
    > query, then you will need to re-bind the datagrid afterwards because the
    > viewstate data will not reflect your data changes.
    >
    > the reason your events are getting lost for the secondary datagrid is
    > because this control does not exist for any given postback unless it is
    > programatically created exactly as it was previously. does that make
    > sense?
    >
    > re: events for a DataBind()... i'm not aware of any knock-on events raised
    > by calling DataBind on a control. if you set a breakpoint at the DataBind
    > call, and hit F11 you will step into any user code that runs as a result
    > of calling Databind.
    >
    > i know what you mean about the complexity of the Page lifecycle. i
    > generally don't concern myself with such events, except obviously
    > Page_Load. there is lots of opinion on where/when to create your dynamic
    > controls. Personally i like to do it all in Page_Load because it is very
    > clear then what is going on, you don't need to worry about the order of
    > events. Page_Load will always run first, and then any events will fire
    > after that. advanced users may say this is too simplistic, but i have done
    > plenty of complex scenarios containing nested dynamic controls only using
    > Page_Load.
    >
    > the official resource on the Page/Postback lifecycle is on MSDN2:
    > http://msdn2.microsoft.com/en-us/library/ms178472.aspx
    > this really is an excellent article and it is the one i was looking for
    > earlier but couldn't find. well worth an afternoon of studying. they
    > also give a few tips for nested databound controls under the heading
    > "catch up events"
    >
    > i am stumped by the double Page_Load. i can't see how Page.Postback could
    > be false unless you have some Response.Redirect code or some javascript to
    > reload the page, or if your linkbutton doesn't directly cause a postback.
    > i.e. if it is rendered as <a href="SamePage.aspx?Select=10">Select</a>
    >
    > can you post the aspx and code-behind? don't worry about the database
    > connections etc, just by looking at the code it may be clear where the
    > problem is.
    >
    > thanks
    > tim
    >
    > "Steve Hershoff" <> wrote in message
    > news:OnV$...
    >> Thanks again Tim. You understand how the dropdown list and the session
    >> variable interact.
    >>
    >> I guess I need to play around a little more. I suppose the way things
    >> work is that when I click the LinkButton a postback is generated, then
    >> the Page_Load is called. I assumed the LinkButton's Click() event
    >> handler would be called even if the datagrid it resides in isn't bound
    >> again, but it appears not?
    >>
    >> One more thing, if you don't mind another question. Would you happen to
    >> know what events are fired or what happens in general on a page when a
    >> DataBind takes place? I ask because in our Page_Load we're binding the
    >> topmost datagrid every time, whether IsPostBack is true or not.
    >>
    >> The first time we enter this page the topmost grid is bound only once.
    >> If I click on a hyperlink to "show the secondary datagrid," the Page_Load
    >> method is called again, with IsPostBack set to true. So far so good.
    >> Again, Page_Load binds the master datagrid.
    >>
    >> However, this time the page is immediately reloaded(?) (IsPostBack equals
    >> false now) and the master datagrid is bound yet again. Only now is the
    >> secondary datagrid loaded and bound.
    >>
    >> I don't understand why Page_Load is called twice in succession? I'm not
    >> reloading or redirecting back to the page, at least not directly in my
    >> code. Strange indeed.
    >>
    >> I keep trying to find good information on the page lifecycle. The
    >> 4guysfromrolla.com site is great for workaday questions involving aspx,
    >> but it's still tough. No two sources seem to agree on what happens.
    >> Either that or they flood you with terms like PagePreRenderInit() and set
    >> your head spinning. Do you happen to have any favored websites or books
    >> that do a good job on this?
    >>
    >> Thanks again for all your help. I really appreciate it.
    >>
    >> -Steve.
    >>
    >>
    >>
    >>
    >> "Tim_Mac" <> wrote in message
    >> news:...
    >>> hi steve, i'm trying to piece together the setup there.
    >>>
    >>> so the drop-down-list SelectedIndexChanged event fires because of your
    >>> code that compares the session variable and updates the SelectedIndex of
    >>> the menu accordingly. that one is explained then?
    >>>
    >>> if you only bind the secondary datagrid in response to a
    >>> SelectedIndexChanged event, then the LinkButton Click event won't fire
    >>> for that datagrid. you need to bind the secondary datagrid for each
    >>> post back where you want to use events with it (especially on the
    >>> Postback that occurs when you click the LinkButton).
    >>>
    >>> you're code should look something like this:
    >>>
    >>> public void Page_Load(...)
    >>> {
    >>> if(!IsPostBack)
    >>> {
    >>> // bind the topmost datagrid and other first time load stuff
    >>> }
    >>> else
    >>> {
    >>> // bind the secondary datagrid, dropdownlist, extra button
    >>> column, etc.
    >>> // exactly as you had it as of the last postback
    >>> }
    >>> }
    >>>
    >>> this approach works for me. if this doesn't give you any ideas, can you
    >>> post your Page_Load and OnInit code, and anything else that affects the
    >>> loading/binding of the dynamic controls. if it's worth it, you may like
    >>> to create a stripped down version of the page and i could test it out
    >>> here.
    >>>
    >>> cheers.
    >>> tim
    >>>

    >>
    >>

    >
    >
     
    Steve Hershoff, Aug 30, 2006
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Steve Hershoff
    Replies:
    6
    Views:
    405
    Steve Hershoff
    Aug 30, 2006
  2. jobs
    Replies:
    0
    Views:
    1,520
  3. SaikiranPuppala
    Replies:
    0
    Views:
    473
    SaikiranPuppala
    Jul 11, 2008
  4. Replies:
    0
    Views:
    272
  5. seal

    Nested Datagrids Events Question

    seal, Mar 22, 2006, in forum: ASP .Net Datagrid Control
    Replies:
    1
    Views:
    158
    Elton Wang
    Mar 23, 2006
Loading...

Share This Page