IsInPartialRendering et IsInAsyncPostBack - comment savoir si un UpdatePanel est en cours de rafraichissement
Le contrôle UpdatePanel possède la propriété IsInPartialRendering, son nom laisse penser que cette propriété vaut true si l'UpdatePanel se met à jour lors de l'AsyncPostBack ... Malheureusement d'après les tests que j'ai fait, cette propriété vaut toujours false. J'ai voulu en savoir plus sur cette propriété, je lance donc Reflector et je découvre que cette propriété est renseignée au début de la phase de rendering de l'UpdatePanel. Il s'agit bien de la phase de rendering, vous ne pouvez pas vous abonnez à l'événement PreRender car celui-ci arrive encore trop tôt.
A quoi peut donc servir cette propriété ? Puisque celle-ci est renseignée lors du rendering de l'UpdatePanel, on peut l'utiliser seulement dans la méthode Render pour les contrôles qui arrivent après l'UpdatePanel en question. Cette propriété peut donc vous servir si vous développez vos contrôles et que vous avez besoin de savoir si le contrôle s'exécute dans un contexte d'AsyncPostBack, c'est à dire dans très rare cas ...
Je trouve donc que cette propriété est inutile, elle est renseigné beaucoup trop tard ! D'après moi cette propriété aurait du être internal plutôt que public ...
Si vous voulez simplement savoir si la page vient d'un AsyncPostBack ou non il vous suffit d'utiliser la propriété IsInAsyncPostBack du ScriptManager, la propriété isInPartialRendering de l'UpdatePanel vous sera inutile.
En rédigeant ce billet je me suis souvenus qu'il existait une documentation sur Atlas, IsInPartialRendering Property
Return Value
true if the current UpdatePanel control is being updated as a result of an asynchronous postback; otherwise, false.
Remarks
The IsInPartialRendering property is intended for use by control developers who want to know when an UpdatePanel control is being updated as a result of an asynchronous postback. In page development scenarios, use the IsInAsyncPostBack property to determine whether a page is processing as a result of an asynchronous postback.
Mais est-il possible de connaitre quel UpdatePanel est en train de se raffraichir ? Voici une méthode qui permet de récuperer un UpdatePanel en cours de raffraichissement.
/// <summary>
/// Finds a refreshed UpdatePanel after an asyncPostback.
/// </summary>
/// <param name="sc">The ScriptManager of the page.</param>
/// <returns></returns>
public static UpdatePanel FindRefreshedUpdatePanel(ScriptManager sc)
{
// Get the control who has fired an asyncpostback and look if it is contains by an UpdatePanel.
Control control = sc.Page.FindControl(sc.AsyncPostBackSourceElementID);
while (control != null)
{
if (control is UpdatePanel)
return (UpdatePanel)control;
control = control.Parent;
}
// if we are here this is because we used a triggers with the UpdatePanel.
return FindRefreshedUpdatePanelRecursive(sc.Page, sc);
}
/// <summary>
/// Finds a refreshed UpdatePanel after an asyncPostback with recursive mode (look at the triggers).
/// </summary>
/// <param name="parent">The parent control.</param>
/// <param name="sc">The ScriptManager of the page.</param>
/// <returns></returns>
/// <remarks>
/// Search for all UpdatePanels contains by the page and look at all this triggers
/// to see if it his associated with the AsyncPostBack source control.
/// </remarks>
private static UpdatePanel FindRefreshedUpdatePanelRecursive(Control parent, ScriptManager sc)
{
foreach (Control child in parent.Controls)
{
if (child is UpdatePanel)
{
foreach (UpdatePanelTrigger trigger in ((UpdatePanel)child).Triggers)
{
String ControlID;
if (trigger is AsyncPostBackTrigger)
ControlID = ((AsyncPostBackTrigger)trigger).ControlID;
else if (trigger is PostBackTrigger)
ControlID = ((PostBackTrigger)trigger).ControlID;
else
continue;
Control c = child.NamingContainer.FindControl(ControlID);
if ((c != null && c.UniqueID == sc.AsyncPostBackSourceElementID) ||
(child.NamingContainer.UniqueID == sc.AsyncPostBackSourceElementID))
return (UpdatePanel)child;
}
}
UpdatePanel control = FindRefreshedUpdatePanelRecursive(child, sc);
if (control != null)
{
return control;
}
}
return null;
}
Cette méthode retourne seulement un des UpdatePanels qui va se rafraichir, pourquoi un seul plutôt que tous ? J'ai fait cette méthode pour pouvoir utiliser la méthode ScriptManager.RegisterStartupScript qui prend en paramètre un Control, pour que la méthode enregistre le script côté client il faut que ce Control fasse partie de l'UpdatePanel en cours de rafraichissement.
Je me suis retrouvé dans ce contexte :
<cyril:myControl id="myControl1" runat="server" MyEvent="myControl1_MyEvent" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Literal id="lit1" runat="server" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="MyControl1" EventName="MyEvent" />
</Triggers>
</asp:UpdatePanel>
Dans la méthode myControl1_MyEvent je devais enregistrer un script coté client, il me fallait donc connaitre l'UpdatePanel en cours de rafraichissement.
J'avais déjà donné ce code il y a quelques temps sur le forum asp.net : How to get which UpdatePanel has posted