Traduction▲
Cet article est la traduction la plus fidèle possible de l'article original : Understanding ASP.NET AJAX UpdatePanel Triggers
B. Introduction▲
http://www.asp.net/learn/ajax/tutorial-02-cs.aspx
La technologie Microsoft ASP.NET apporte un modèle de programmation orientée objet et piloté par les évènements et l'unit avec les avantages du code compilé. Toutefois, son modèle de traitement côté serveur a plusieurs inconvénients inhérents à la technologie dont beaucoup peuvent être adressés par les nouvelles fonctionnalités incluses dans Microsoft ASP.NET 3.5 AJAX Extensions. Ces extensions apportent de nombreuses nouvelles fonctionnalités de client riche, notamment le rendu partiel de pages sans exiger de rafraîchissement complet de la page, la capacité d'accéder à des services Web via du script client (y compris l'API de gestion de profil d'ASP.NET) et une API extensible coté client destinées à faire miroir avec bon nombre de mécanismes des contrôles serveurs ASP.NET.
Ce livre blanc présente les fonctionnalités liée aux Triggers du composant UpdatePanel d'ASP.NET AJAX.
Ce livre blanc est basée sur la version bêta 2 du Framework .NET 3.5 et Visual Studio 2008. Les ASP.NET AJAX Extensions, qui étaient précédemment un add-on sous forme d'assembly destinées à ASP.NET 2.0, sont désormais intégrées dans la Base Class Library du Framework .NET. Ce livre blanc suppose également que vous travaillez avec Visual Studio 2008, et non pas Visual Web Developer Express, et fournira des pas à pas en fonction de l'interface utilisateur de Visual Studio (bien que le code soit entièrement compatible quel que soit l'environnement de développement).
C. Triggers▲
Les déclencheurs pour un UpdatePanel donné incluent automatiquement par défaut tous les contrôles enfants qui invoquent un postback, y compris (par exemple) les contrôles TextBox qui ont leur propriété AutoPostBack à true. Cependant, les déclencheurs peuvent également être inclus de façon déclarative en utilisant une balise, cela se fait dans la section <triggers> de la déclaration du contrôle UpdatePanel. Bien que l'on puisse accéder aux déclencheurs via la propriété Triggers (collection), il est recommandé d'enregistrer les déclencheurs de rendu partiel au moment de l'exécution (par exemple, si un contrôle n'est pas disponible en mode design) en utilisant la méthode RegisterAsyncPostBackControl(Control) de l'objet ScriptManager de votre page, dans l'événement Page_Load. Rappelez-vous que les pages sont sans état, et donc vous devriez réenregistrer ces contrôles à chaque fois qu'ils sont créés.
L'inscription automatique des contrôles enfants peut aussi être désactivée (pour que les contrôles enfants qui créent des postbacks ne déclenchent pas automatiquement des rendus partiels) en positionnant à false la propriété ChildrenAsTriggers. Cela vous permet la plus grande souplesse dans l'attribution des contrôles qui peuvent provoquer le rendu d'une page.
Notez que lorsque les contrôles UpdatePanel sont imbriqués, et que l'UpdateMode est positionné sur Conditionnal, si l'UpdatePanel enfant est déclenché, mais que le parent ne l'est pas, seul l'UpdatePanel enfant se rafraîchira.
D. L'élément <Triggers>▲
En travaillant dans l'éditeur de balisage dans Visual Studio, vous avez dû remarquer (grâce à l'IntelliSense) qu'il existe deux éléments enfants pour un contrôle UpdatePanel. Le plus fréquemment rencontré est l'élément <ContentTemplate>, qui encapsule le contenu qui sera tenue à jour par l'UpdatePanel (le contenu pour lequel nous avons activé le rendu partiel). L'autre élément est l'élément <Triggers>, qui définit les contrôles sur la page (ou le contrôle utilisateur, si vous en utilisez un) qui vont déclencher un rendu partiel du contrôle UpdatePanel dans lequel l'élément réside.
L'élément <Triggers> peut contenir un nombre quelconque des deux nouds enfants: <asp:AsyncPostBackTrigger> et <asp:PostBackTrigger>. Tout deux acceptent deux attributs, ControlID et EventName et peuvent référencer tout contrôle se trouvant dans l'unité d'encapsulation courante (par exemple, si votre contrôle UpdatePanel réside dans un contrôle utilisateur, vous ne devriez pas tenter de référencer un contrôle se trouvant sur la page sur laquelle le UserControl résidera).
L'élément <asp:AsyncPostBackTrigger> est particulièrement utile en ce qu'il permet de cibler tous les évènements provenant d'un contrôle qui existe en tant qu'enfant de n'importe quel contrôle UpdatePanel dans l'unité d'encapsulation, et pas seulement de l'UpdatePanel dont ce déclencheur est l'enfant.
De même, l'élément <asp:PostBackTrigger> peut être utilisé pour déclencher un rendu partiel de page, mais un qui nécessite un aller-retour au serveur. Cet élément déclencheur peut également être utilisé pour forcer un rendu complet de page quand un contrôle aurait normalement déclenché un rendu partiel de page (par exemple, quand un contrôle Button existe dans l'élément <ContentTemplate> d'un contrôle UpdatePanel). Encore une fois, l'élément PostBackTrigger peut référencer un contrôle qui est un enfant de n'importe quel contrôle UpdatePanel dans l'unité d'encapsulation courante.
E. <Triggers> Element Reference <Triggers> Élément de référence▲
Eléments descendants :
Tag Tag | Description Description |
<asp:AsyncPostBackTrigger> | Specifies a control and event that will cause a partial page update for the UpdatePanel that contains this trigger reference. Spécifie un contrôle et d'événement qui cause une partie de la page mise à jour pour UpdatePanel qui contient ce déclencheur de référence. |
<asp:PostBackTrigger> | Specifies a control and event that will cause a full page update (a full page refresh). Spécifie un contrôle et d'événements qui vont provoquer une pleine page de mise à jour (une page entière de rafraîchissement). This tag can be used to force a full refresh when a control would otherwise trigger partial rendering. Cette balise peut être utilisée pour forcer un rafraîchissement d'un contrôle partiel, sinon de déclencher le rendu. |
F. Pas à pas▲
Créez une nouvelle page ASP.NET avec un objet ScriptManager pour permettre un rendu partiel. Ajoutez deux UpdatePanels sur cette page - dans le premier, incluez un contrôle Label ("Label1") et deux contrôles Button ("Button1" et "Button2"). Le texte de Button1 sera "Update Both Panels" et celui de Button2 sera "Update This Panel", ou quelque chose du genre. Dans le deuxième UpdatePanel, incluez uniquement un contrôle Label ("label2"), mais mettez sa propriété ForeColor à autre chose que la valeur par défaut afin de le différencier.
Définissez la propriété UpdateMode des deux balises UpdatePanel à Conditional.
<%
@ Page Language=
"C#"
AutoEventWireup=
"true"
CodeFile=
"Default.aspx.cs"
Inherits=
"_Default"
%>
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
>
<html xmlns
=
"http://www.w3.org/1999/xhtml"
>
<head runat
=
"server"
>
<title>
Untitled Page</title>
</head>
<body>
<form id
=
"form1"
runat
=
"server"
>
<asp:ScriptManager EnablePartialRendering
=
"true"
ID
=
"ScriptManager1"
runat
=
"server"
></asp:ScriptManager>
<div>
<asp:UpdatePanel ID
=
"UpdatePanel1"
runat
=
"server"
UpdateMode
=
"Conditional"
>
<ContentTemplate>
<asp:Label ID
=
"Label1"
runat
=
"server"
/><br />
<asp:Button ID
=
"Button1"
runat
=
"server"
Text
=
"Update Both Panels"
OnClick
=
"Button1_Click"
/>
<asp:Button ID
=
"Button2"
runat
=
"server"
Text
=
"Update This Panel"
OnClick
=
"Button2_Click"
/>
</ContentTemplate>
</asp:UpdatePanel>
<asp:UpdatePanel ID
=
"UpdatePanel2"
runat
=
"server"
UpdateMode
=
"Conditional"
>
<ContentTemplate>
<asp:Label ID
=
"Label2"
runat
=
"server"
ForeColor
=
"red"
/>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID
=
"Button1"
EventName
=
"Click"
/>
</Triggers>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
Dans le gestionnaire d'événements Click de Button1, assignez Label1.Text et Label2.Text à quelque chose de dépendant du temps (comme DateTime.Now.ToLongTimeString ()). Pour le gestionnaire d'événements Click pour Button2, assignez seulement Label1.Text à une valeur en dépendant du temps.
public partial class _Default : System.Web.UI.Page
{
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = DateTime.Now.ToLongTimeString();
Label2.Text = DateTime.Now.ToLongTimeString();
}
protected void Button2_Click(object sender, EventArgs e)
{
Label1.Text = DateTime.Now.ToLongTimeString();
}
}
Appuyez sur F5 pour générer et exécuter le projet. Notez que, lorsque vous cliquez sur "Update Both Panels", les deux labels voient leur texte changer, mais lorsque vous cliquez sur "Update This Panel", seul Label1 se met à mise à jour
G. Sous le capot▲
En utilisant l'exemple que nous venons de construire, nous pouvons jeter un oeil à ce qu'ASP.NET AJAX fait et comment notre UpdatePanel fonctionne. Pour ce faire, nous allons travailler avec la source HTML de la page générée, ainsi que l'extension pour Firefox appelée Firebug - avec elle, nous pouvons facilement examiner les postbacks AJAX. Nous allons également utiliser l'outil .NET Reflector de Lutz Roeder. Ces deux outils sont disponibles librement en ligne, et peuvent être trouvés avec une recherche sur Internet.
Un examen de la page de code source ne montre presque rien qui sorte de l'ordinaire, les contrôles UpdatePanel sont rendus comme des conteneurs <div>, et l'on peut voir la ressource script fournie par le <asp:ScriptManager>. Il y a aussi quelques appels au PageRequestManager spécifiques à AJAX qui sont internent à la bibliothèque de script cliente AJAX. Enfin, nous voyons les deux conteneurs UpdatePanel - un avec les boutons rendu comme balise <input> avec les deux contrôles <asp:Label> rendus comme conteneurs <span>. Si vous regardez dans l'arborescence DOM dans Firebug, vous remarquerez que les labels sont grisés pour indiquer qu'ils ne produisent pas de contenu visible.
Cliquez sur le bouton "Update This Panel", et remarquez le haut de l'UpdatePanel qui sera mis à jour avec la date du serveur. Dans Firebug, choisissez l'onglet "Console" pour que vous puissiez examiner la requête. Examinez les paramètres POST de la requête en premier:
Notez que l'UpdatePanel a indiqué au code AJAX côté serveur précisément quel contrôle de l'arbre a été tiré par le paramètre ScriptManager1: Button1 du contrôle UpdatePanel1. Maintenant, cliquez sur le bouton "Update Both Panels". Ensuite, en examinant la réponse, on voit une série de variables dans une chaîne de caractères, en particulier, nous voyons que l'UpdatePanel du haut, UpdatePanel1, a l'intégralité de son HTML envoyé au navigateur. La bibliothèque cliente de scripts AJAX remplace le contenu HTML d'origine de l'UpdatePanel avec le nouveau contenu via la propriété .innerHTML, de sorte que le serveur renvoie le contenu qui a changé en HTML.
Maintenant, cliquez sur le bouton "Update Both Panels" et examinez les résultats venant du serveur. Les résultats sont très semblables - les deux UpdatePanels reçoivent le nouvel HTML à partir du serveur. Comme pour les précédents callback, l'état additionnel de la page est envoyé.
Comme on peut le voir, parce qu'aucun code spécial n'est utilisé pour effectuer un postback AJAX, la bibliothèque cliente de scripts AJAX est en mesure d'intercepter les postbacks de formulaire sans code supplémentaire. Les contrôles serveur utilisent automatiquement JavaScript afin de ne pas soumettre le formulaire automatiquement - ASP.NET injecte automatiquement du code pour la validation du formulaire, réalisé essentiellement par les classes PostBackOptions, ClientScriptManager.
Par exemple, considérez un contrôle CheckBox; examinez le désassemblage de la classe dans .NET Reflector. Pour ce faire, assurez-vous que votre assembly System.Web est ouverte, et accéder à la classe System.Web.UI.WebControls.CheckBox, et ouvrez la méthode RenderInputTag. Rechercher une condition qui vérifie la propriété AutoPostBack :
Lorsque le postback automatique est activé sur un contrôle CheckBox (par l'intermédiaire de la propriété AutoPostBack mise à true), le tag <input> résultant est alors rendu avec un script ASP.NET de gestion d'événement dans son attribut onclick. Les interceptions de la soumission du formulaire, permettent à ASP.NET AJAX d'être injecté dans la page de façon non intrusive, en contribuant à éviter tout risque de cassures qui pourraient éventuellement survenir en utilisant une possible imprécise chaîne de caractères de remplacement. En outre, cette mesure permet à tout contrôle ASP.NET personnalisé d'utiliser la puissance de ASP.NET AJAX sans aucun code à supplémentaire pour supporter son utilisation au sein d'un conteneur UpdatePanel.
La fonctionnalité <triggers> correspond à la valeur initialisée dans l'appel du PageRequestManager à _updateControls (notez que la bibliothèque de script client ASP.NET AJAX utilise la convention telle que les méthodes, les événements et les noms de champs commençant par un underscore sont marqués comme étant internes (internal), et ne sont pas sujet à être utilisés en dehors de la bibliothèque elle-même). Avec ça, nous pouvons savoir quels contrôles sont destinés à causer un postbacks AJAX.
Par exemple, nous allons ajouter deux contrôles supplémentaires à la page, en laissant un contrôle à l'extérieur des UpdatePanels, et en en laissant un dans un UpdatePanel. Nous allons ajouter une case à cocher dans la partie supérieure de l'UpdatePanel, et une DropDownList contenant un nombre de couleurs définies. Voici le code ASP.NET correspondant :
<%
@ Page Language=
"C#"
AutoEventWireup=
"true"
CodeFile=
"Default.aspx.cs"
Inherits=
"_Default"
%>
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
>
<html xmlns
=
"http://www.w3.org/1999/xhtml"
>
<head id
=
"Head1"
runat
=
"server"
>
<title>
Untitled Page</title>
</head>
<body>
<form id
=
"form2"
runat
=
"server"
>
<asp:ScriptManager EnablePartialRendering
=
"true"
ID
=
"ScriptManager2"
runat
=
"server"
></asp:ScriptManager>
<div>
<asp:UpdatePanel ID
=
"UpdatePanel1"
runat
=
"server"
UpdateMode
=
"Conditional"
>
<ContentTemplate>
<asp:Label ID
=
"Label1"
runat
=
"server"
/><br />
<asp:Button ID
=
"Button1"
runat
=
"server"
Text
=
"Update Both Panels"
OnClick
=
"Button1_Click"
/>
<asp:Button ID
=
"Button2"
runat
=
"server"
Text
=
"Update This Panel"
OnClick
=
"Button2_Click"
/>
<asp:CheckBox ID
=
"cbDate"
runat
=
"server"
Text
=
"Include Date"
AutoPostBack
=
"false"
OnCheckedChanged
=
"cbDate_CheckedChanged"
/>
</ContentTemplate>
</asp:UpdatePanel>
<asp:UpdatePanel ID
=
"UpdatePanel2"
runat
=
"server"
UpdateMode
=
"Conditional"
>
<ContentTemplate>
<asp:Label ID
=
"Label2"
runat
=
"server"
ForeColor
=
"red"
/>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID
=
"Button1"
EventName
=
"Click"
/>
<asp:AsyncPostBackTrigger ControlID
=
"ddlColor"
EventName
=
"SelectedIndexChanged"
/>
</Triggers>
</asp:UpdatePanel>
<asp:DropDownList ID
=
"ddlColor"
runat
=
"server"
AutoPostBack
=
"true"
OnSelectedIndexChanged
=
"ddlColor_SelectedIndexChanged"
>
<asp:ListItem Selected
=
"true"
Value
=
"Red"
/>
<asp:ListItem Value
=
"Blue"
/>
<asp:ListItem Value
=
"Green"
/>
</asp:DropDownList>
</div>
</form>
</body>
</html>
Et voici le code C# associé:
public
partial
class
_Default :
System.
Web.
UI.
Page
{
protected
void
Button1_Click
(
object
sender,
EventArgs e)
{
if
(
cbDate.
Checked)
{
Label1.
Text =
DateTime.
Now.
ToString
(
"MM/dd/yyyy hh:mm:ss"
);
Label2.
Text =
DateTime.
Now.
ToString
(
"MM/dd/yyyy hh:mm:ss"
);
}
else
{
Label1.
Text =
DateTime.
Now.
ToLongTimeString
(
);
Label2.
Text =
DateTime.
Now.
ToLongTimeString
(
);
}
}
protected
void
Button2_Click
(
object
sender,
EventArgs e)
{
if
(
cbDate.
Checked)
{
Label1.
Text =
DateTime.
Now.
ToString
(
"MM/dd/yyyy hh:mm:ss"
);
}
else
{
Label1.
Text =
DateTime.
Now.
ToLongTimeString
(
);
}
}
protected
void
cbDate_CheckedChanged
(
object
sender,
EventArgs e)
{
cbDate.
Font.
Bold =
cbDate.
Checked;
}
protected
void
ddlColor_SelectedIndexChanged
(
object
sender,
EventArgs e)
{
Color c =
Color.
FromName
(
ddlColor.
SelectedValue);
Label2.
ForeColor =
c;
}
}
L'idée derrière cette page est que la sélection d'une couleur dans la liste déroulante modifie la couleur du second label, que la case à cocher détermine si le texte est en gras ou non, et que les labels affichent la date ainsi que l'heure. La case à cocher ne devrait pas causer une mise à jour AJAX, mais la liste déroulante devrait, même si elle ne se trouve pas dans un UpdatePanel.
Comme il ressort de la copie d'écran ci-dessus, le bouton le plus récent à avoir été cliqué est le bouton droit "Update This Panel", qui a mis à jour la date du haut indépendamment du temps affiché en bas. Le dernier point d'intérêt est la couleur de fond du label: elle a été mise à jour plus récemment que le texte du label, ce qui démontre que l'état des contrôles est important, et les utilisateurs s'attendent à ce qu'il soit préservé au travers des postbacks AJAX. Toutefois, le temps n'a pas été mis à jour. Le temps a été automatiquement repeuplé grâce à la persistance du champ __VIEWSTATE de la page qui a été interprété par le runtime ASP.NET lorsque le contrôle a été de nouveau rendu sur le serveur. Le code serveur ASP.NET AJAX ne reconnaît pas dans quelle méthode les contrôles sont en train de changer l'état, il s'occupe simplement de repeupler à partir du viewstate puis exécute les événements qui sont appropriés. Il convient de souligner, toutefois, que si nous avions initialisé le temps dans l'événement Page_Load, le temps aurait été incrémenté correctement. En conséquence, les développeurs doivent faire attention à ce que le code s'exécute pendant les événements appropriés et éviter l'utilisation de Page_Load quand un gestionnaire d'événement sur un contrôle est plus approprié.
H. Conclusion▲
Le contrôle méthodes des ASP.NET AJAX Extensions est versatile, et peut utiliser un certain nombre de méthodes pour identifier les événements de contrôle qui devraient l'amener à être mis à jour. Il supporte les mises à jour automatiquement par ses contrôles enfants, mais peut aussi répondre à d'autres événements de contrôle sur la page.
Afin de réduire la charge de traitement du serveur, il est recommandé que la propriété ChildrenAsTriggers d'un UpdatePanel soit mise à false et que les événements soient choisis plutôt qu'inclus par défaut. Cela évite également que des événements inutiles ne causent potentiellement des effets indésirables, comme par exemple la validation, et des modifications sur des champs de saisie. Ces types de bugs peuvent être difficiles à isoler, car la mise à jour de la page est transparente pour l'utilisateur, et la cause peut donc ne pas être immédiatement évidente.
En examinant le fonctionnement interne du model ASP.NET AJAX d'interception de post de formulaire, nous avons été en mesure de déterminer qu'il utilise le Framework déjà fourni par ASP.NET. Ce faisant, il préserve un maximum de compatibilité avec les contrôles utilisant ce même Framework, et s'immisce de façon minimale sur le JavaScript écrit pour la page.