With partial page updates it becomes more feasible to create pages with no viewstate, however this requires a bit trickier coding. I have a DropDownList control that I need to rebind every time I am refreshing the UpdatePanel that contains it. The first
thought is to put the binding process in the event handler of the item that caused the partial postback. However, since this occurs in the pipeline after the DropDown's selected value is applied, the selected value is lost. Thus the binding of the DropDown
has to happen in the Page_Init stage. But at this stage I don't have the event yet unless you examine the raw posted data (ugly). It would be nice if the ScriptManager could be interogated on post back to tell us which UpdatePanel caused the partial post.
Then in the Page_Init I can say "If the UpdatePanel doing the posting contains my DropDown then do the binding". I have not seen any way to get a reference of the UpdatePanel that contains the control that triggered the partial post back. If it exists I would
like to know.
Instead of interogating the ScriptManager we can interogate each UpdatePanel's IsInPartialRendering property to know if an update panel is part of the asynchronous postback. Maybe you can figure a way around this property instead.
There is one more case. UpdatePanel can be refreshed using a submit button or another control inside it. In that case you would need to use code like this:
Control control=this.Page.FindControl(scriptManager.AsyncPostBackSourceElementID);
while (control != null)
{
if (control is UpdatePanel)
return (UpdatePanel)control;
Actually, it gets worse. Both code blocks above make the assumption that the triggering AsyncPostBackSourceElementID is a child of the UpdatePanel in question. This is by no means a safe assumption.
External triggers could set it off. The only way I can see to ensure that you've unequivocally determined which UpdatePanel is being processed is to iterate the UpdatePanels (for which there is no simple method), iterate their triggers (which have to be
cast either to PostBackTrigger or AsyncPostBackTrigger to get the ControlID), and compare said ControlIDs with the AsyncPostBackSourceElementID. If you try to generalize it across all the UpdatePanels on a page, it gets pretty Rube Goldberg. I'm using the
following code to tell if a specific panel is being updated:
private bool IsUpdating(ScriptManager sm, UpdatePanel up) {
string elemID = sm.AsyncPostBackSourceElementID;
foreach (UpdatePanelTrigger t in up.Triggers) {
PostBackTrigger pt = t as PostBackTrigger;
if (pt != null)
if (pt.ControlID == elemID)
return true;
AsyncPostBackTrigger apt = t as AsyncPostBackTrigger;
if (apt != null)
if (apt.ControlID == elemID)
return true;
}
return false;
}
Why the UpdatePanel doesn't provide an event to indicate that it's getting partially updated is quite beyond me. This seems like a glaring hole in the implementation. If there was a compelling reason to leave this out, I'd be very curious to hear it.
I didn't get a really good look at your code before posting. You do seem to have the problem covered pretty well. One thing neither of us handles quite right is the case where a single control might trigger the update of multiple panels.
Still, does anyone else find it just a bit crazy that we have to go to this monumental effort just to determine which panels are being updated? There should be a better way.
The better way would be if UpdatePanel.IsInPartialRendering would actually return the correct value. Unfortunately it doesn't work correctly and always seems to return false.
Right now Cyril's and my code only returns the first UpdatePanel, but it should be pretty easy to modify our code to return a list of all panels being refreshed.
Bort
Member
19 Points
51 Posts
how to get which UpdatePanel has posted
Dec 20, 2006 11:15 AM|LINK
With partial page updates it becomes more feasible to create pages with no viewstate, however this requires a bit trickier coding. I have a DropDownList control that I need to rebind every time I am refreshing the UpdatePanel that contains it. The first thought is to put the binding process in the event handler of the item that caused the partial postback. However, since this occurs in the pipeline after the DropDown's selected value is applied, the selected value is lost. Thus the binding of the DropDown has to happen in the Page_Init stage. But at this stage I don't have the event yet unless you examine the raw posted data (ugly). It would be nice if the ScriptManager could be interogated on post back to tell us which UpdatePanel caused the partial post. Then in the Page_Init I can say "If the UpdatePanel doing the posting contains my DropDown then do the binding". I have not seen any way to get a reference of the UpdatePanel that contains the control that triggered the partial post back. If it exists I would like to know.
Thanks
bogdanb
Member
65 Points
30 Posts
Re: how to get which UpdatePanel has posted
Dec 20, 2006 02:17 PM|LINK
Instead of interogating the ScriptManager we can interogate each UpdatePanel's IsInPartialRendering property to know if an update panel is part of the asynchronous postback. Maybe you can figure a way around this property instead.
Bogdan
Bort
Member
19 Points
51 Posts
Re: how to get which UpdatePanel has posted
Dec 20, 2006 08:59 PM|LINK
Bort
Member
19 Points
51 Posts
Re: how to get which UpdatePanel has posted
Dec 20, 2006 09:08 PM|LINK
Steve Marx
Contributor
2460 Points
643 Posts
Re: how to get which UpdatePanel has posted
Dec 20, 2006 09:09 PM|LINK
ScriptManager
.GetCurrent(Page).AsyncPostBackSourceElementIDto see what caused the async postback.
CyrilCS
Contributor
6465 Points
22 Posts
Re: how to get which UpdatePanel has posted
Dec 20, 2006 11:31 PM|LINK
Hi,
I think this code would help you.
<div style="FONT-SIZE: 10pt; BACKGROUND: white; COLOR: black; FONT-FAMILY: Courier New">86 private static UpdatePanel FindRefreshedUpdatePanelRecursive(Control parent, ScriptManager sc)
87 {
88 foreach (Control child in parent.Controls)
89 {
90 if (child is UpdatePanel)
91 {
92 foreach (UpdatePanelTrigger trigger in ((UpdatePanel)child).Triggers)
93 {
94 String ControlID;
95 if (trigger is AsyncPostBackTrigger)
96 ControlID = ((AsyncPostBackTrigger)trigger).ControlID;
97 else if (trigger is PostBackTrigger)
98 ControlID = ((PostBackTrigger)trigger).ControlID;
99 else
100 continue;
101
102 if (child.NamingContainer.FindControl(ControlID).UniqueID == sc.AsyncPostBackSourceElementID)
103 return (UpdatePanel)child;
104 }
105 }
106 UpdatePanel c = FindRefreshedUpdatePanelRecursive(child, sc);
107 if (c != null)
108 {
109 return c;
110 }
111 }
112 return null;
113 }
</div>ericpopivker
Member
73 Points
22 Posts
Re: how to get which UpdatePanel has posted
Dec 22, 2006 04:43 PM|LINK
Thanks for the code, Cyril...
There is one more case. UpdatePanel can be refreshed using a submit button or another control inside it. In that case you would need to use code like this:
Control control=this.Page.FindControl(scriptManager.AsyncPostBackSourceElementID);
while (control != null)
{
if (control is UpdatePanel)
return (UpdatePanel)control;
control = control.Parent;
}
return null;
Regards,
Eric
ewlloyd
Member
21 Points
6 Posts
Re: how to get which UpdatePanel has posted
Dec 22, 2006 07:04 PM|LINK
Gents,
Actually, it gets worse. Both code blocks above make the assumption that the triggering AsyncPostBackSourceElementID is a child of the UpdatePanel in question. This is by no means a safe assumption.
External triggers could set it off. The only way I can see to ensure that you've unequivocally determined which UpdatePanel is being processed is to iterate the UpdatePanels (for which there is no simple method), iterate their triggers (which have to be cast either to PostBackTrigger or AsyncPostBackTrigger to get the ControlID), and compare said ControlIDs with the AsyncPostBackSourceElementID. If you try to generalize it across all the UpdatePanels on a page, it gets pretty Rube Goldberg. I'm using the following code to tell if a specific panel is being updated:
private bool IsUpdating(ScriptManager sm, UpdatePanel up) { string elemID = sm.AsyncPostBackSourceElementID; foreach (UpdatePanelTrigger t in up.Triggers) { PostBackTrigger pt = t as PostBackTrigger; if (pt != null) if (pt.ControlID == elemID) return true; AsyncPostBackTrigger apt = t as AsyncPostBackTrigger; if (apt != null) if (apt.ControlID == elemID) return true; } return false; }Why the UpdatePanel doesn't provide an event to indicate that it's getting partially updated is quite beyond me. This seems like a glaring hole in the implementation. If there was a compelling reason to leave this out, I'd be very curious to hear it.
Cheers!
Eric
updatepanel ajax "Using UpdatePanel" "AsyncPostbackTrigger"
ewlloyd
Member
21 Points
6 Posts
Re: how to get which UpdatePanel has posted
Dec 22, 2006 07:14 PM|LINK
My apologies, Cyril.
I didn't get a really good look at your code before posting. You do seem to have the problem covered pretty well. One thing neither of us handles quite right is the case where a single control might trigger the update of multiple panels.
Still, does anyone else find it just a bit crazy that we have to go to this monumental effort just to determine which panels are being updated? There should be a better way.
Cheers!
Eric
ericpopivker
Member
73 Points
22 Posts
Re: how to get which UpdatePanel has posted
Dec 22, 2006 07:25 PM|LINK
Hi Eric,
The better way would be if UpdatePanel.IsInPartialRendering would actually return the correct value. Unfortunately it doesn't work correctly and always seems to return false.
Right now Cyril's and my code only returns the first UpdatePanel, but it should be pretty easy to modify our code to return a list of all panels being refreshed.
Regards,
Eric P