Other day I was experimenting with finding which UpdatePanel will be updated during page post back.
I found out that my solution was not working correctly for complex triggers, like user controls with custom events, which will trigger async postbacks and update of panel.
Or for grids with buttons. It was big issue. Also it was not pointing to correct UpdatePanel
if name of control was not entirely unique (for example when you have multiple same custom controls on page). It would return first panel, even if it wasn’t updating.
So here is updated code:
public static UpdatePanel FindAsyncPostBackUpdatePanel(this Page page) { var scriptManager = ScriptManager.GetCurrent(page); var pageRequestMngr = scriptManager.GetNonPublicProperty<object>("PageRequestManager"); var updatePanels = pageRequestMngr.GetNonPublicField<List<UpdatePanel>>("_allUpdatePanels"); var source = page.FindControl(scriptManager.AsyncPostBackSourceElementID); UpdatePanel parentUp = null; //check if is child of update parent with children as triggers Control parent = source.Parent; while (parent != null && parentUp == null) { parent = parent.Parent; parentUp = parent as UpdatePanel; if (parentUp != null && (CheckIfPostbackSourceInTriggers(source, parentUp) || parentUp.ChildrenAsTriggers || (parentUp.IsInPartialRendering || parentUp.GetNonPublicProperty<bool>("RequiresUpdate")))) { break; } parentUp = null; } if (parentUp != null) return parentUp; foreach (var up in updatePanels) { if (CheckIfPostbackSourceInTriggers(source, up)) return up; } return null; } private static bool CheckIfPostbackSourceInTriggers(Control source, UpdatePanel up) { foreach (var trigger in up.Triggers) { var t = trigger as AsyncPostBackTrigger; if (t == null) { continue; } if (t.GetNonPublicField<Control>("_associatedControl").UniqueID == source.UniqueID) { return true; } } return false; }
What have changed?
1. I added code for traversing parent controls of our source control. Most of the time control that is causing post back is children of UpdatePanel
. Such a loop is much quicker then finding out all of UpdatePanels
, and checking its triggers.
Also if grid with some grid-specific event caused UpdatePanel
to update, this grid probably will be child of UpdatePanel
and so will be button from that grid. Still it’s not ideal. If you have grid with some entities (customers for example), and you want to clicking at some customer will open it’s edit view in UpdatePanel
in some other part of page. Source and UpdatePanel
are not in child-parent relation.
If source is child of UpdatePanel
method will check if ChildrenAsTriggers
is true
– panel will be updated cause it’s triggered by child.
If IsInPartialRendering
flag and RequiresUpdate
, after some test I can say that that this flags indicates if UpdatePanel
will be updated. Interesting thing that first flag was not true even if given UpdatePanel
was indeed updating. I don’t know why. But second flag non-public property was true in those situations.
2. Checking only for control Id was not reliable since it doesn’t must be unique for page. That’s why I am checking for unique id, of non-public field with trigger control instance and source unique id. That have to give correct answer only for one control, but is much slower since is using reflection.
That’s it for now but I feel that I will have to revise that code once again soon 🙂