Partager via


Présentation des déclencheurs UpdatePanel d’ASP.NET AJAX

par Scott Cate

Lorsque vous travaillez dans l’éditeur de balisage dans Visual Studio, vous pouvez remarquer (à partir d’IntelliSense) qu’il existe deux éléments enfants d’un contrôle UpdatePanel. L’un d’entre eux est l’élément Triggers, qui spécifie les contrôles sur la page (ou le contrôle utilisateur, si vous en utilisez un) qui déclenchera un rendu partiel du contrôle UpdatePanel dans lequel réside l’élément.

Introduction

La technologie ASP.NET de Microsoft apporte un modèle de programmation orienté objet et piloté par les événements et l’associe aux avantages du code compilé. Toutefois, son modèle de traitement côté serveur présente plusieurs inconvénients inhérents à la technologie, dont beaucoup peuvent être traités par les nouvelles fonctionnalités incluses dans les extensions Microsoft ASP.NET AJAX 3.5. Ces extensions permettent de nombreuses nouvelles fonctionnalités client enrichies, notamment le rendu partiel des pages sans nécessiter une actualisation complète de la page, la possibilité d’accéder aux services web via un script client (y compris l’API de profilage ASP.NET) et une API côté client étendue conçue pour miroir la plupart des schémas de contrôle vus dans l’ensemble de contrôles côté serveur ASP.NET.

Ce livre blanc examine la fonctionnalité Déclencheurs XML du composant AJAX UpdatePanel ASP.NET. Les déclencheurs XML donnent un contrôle granulaire sur les composants qui peuvent entraîner un rendu partiel pour des contrôles UpdatePanel spécifiques.

Ce livre blanc est basé sur la version bêta 2 du .NET Framework 3.5 et de Visual Studio 2008. Les extensions ASP.NET AJAX, précédemment un assembly de module complémentaire destiné à ASP.NET 2.0, sont désormais intégrées à la bibliothèque de classes de base .NET Framework. Ce livre blanc suppose également que vous allez utiliser Visual Studio 2008, et non Visual Web Developer Express, et fournit des procédures pas à pas en fonction de l’interface utilisateur de Visual Studio (bien que les listes de code soient entièrement compatibles quel que soit l’environnement de développement).

Déclencheurs

Par défaut, les déclencheurs d’un UpdatePanel donné incluent automatiquement tous les contrôles enfants qui appellent une publication, y compris (par exemple) les contrôles TextBox dont la AutoPostBack propriété est définie sur true. Toutefois, les déclencheurs peuvent également être inclus de manière déclarative à l’aide du balisage ; Cette opération est effectuée dans la <triggers> section de la déclaration de contrôle UpdatePanel. Bien que les déclencheurs soient accessibles via la Triggers propriété collection, il est recommandé d’inscrire tous les déclencheurs de rendu partiel au moment de l’exécution (pour instance, si un contrôle n’est pas disponible au moment du design) à l’aide de la RegisterAsyncPostBackControl(Control) méthode de l’objet ScriptManager pour votre page, dans l’événement Page_Load . N’oubliez pas que les pages sont sans état et que vous devez donc réinscrire ces contrôles chaque fois qu’ils sont créés.

L’inclusion automatique d’un déclencheur enfant peut également être désactivée (de sorte que les contrôles enfants qui créent des publications ne déclenchent pas automatiquement des rendus partiels) en définissant la ChildrenAsTriggers propriété sur false. Cela vous offre la plus grande flexibilité dans l’attribution des contrôles spécifiques qui peuvent appeler un rendu de page, et est recommandé, afin qu’un développeur accepte de répondre à un événement, plutôt que de gérer les événements qui peuvent survenir.

Notez que lorsque les contrôles UpdatePanel sont imbriqués, lorsque UpdateMode est défini sur Conditionnel, si le UpdatePanel enfant est déclenché, mais que le parent ne l’est pas, seul le UpdatePanel enfant s’actualise. Toutefois, si le UpdatePanel parent est actualisé, le UpdatePanel enfant est également actualisé.

Élément <Triggers>

Lorsque vous travaillez dans l’éditeur de balisage dans Visual Studio, vous pouvez remarquer (à partir d’IntelliSense) qu’il existe deux éléments enfants d’un UpdatePanel contrôle. L’élément le plus fréquemment vu est l’élément <ContentTemplate> , qui encapsule essentiellement le contenu qui sera conservé par le panneau de mise à jour (le contenu pour lequel nous activons le rendu partiel). L’autre élément est l’élément <Triggers> , qui spécifie les contrôles de la page (ou le contrôle utilisateur, si vous en utilisez un) qui déclenche un rendu partiel du contrôle UpdatePanel dans lequel réside l’élément <Triggers> .

L’élément <Triggers> peut contenir n’importe quel nombre chacun de deux nœuds enfants : <asp:AsyncPostBackTrigger> et <asp:PostBackTrigger>. Ils acceptent tous les deux attributs, ControlID et EventName, et peuvent spécifier n’importe quel contrôle dans l’unité actuelle d’encapsulation (pour instance, si votre contrôle UpdatePanel réside dans un contrôle utilisateur web, vous ne devez pas tenter de référencer un contrôle sur la page sur laquelle le contrôle utilisateur réside).

L’élément <asp:AsyncPostBackTrigger> est particulièrement utile dans la mesure où il peut cibler n’importe quel événement à partir d’un contrôle Control qui existe en tant qu’enfant de n’importe quel contrôle UpdatePanel dans l’unité d’encapsulation, et pas seulement le UpdatePanel sous lequel ce déclencheur est un enfant. Ainsi, n’importe quel contrôle peut être effectué pour déclencher une mise à jour partielle de la page.

De même, l’élément <asp:PostBackTrigger> peut être utilisé pour déclencher un rendu de page partiel, mais qui nécessite un aller-retour complet vers le serveur. Cet élément déclencheur peut également être utilisé pour forcer un rendu de page complète alors qu’un contrôle déclencherait normalement un rendu de page partiel (pour instance, lorsqu’un Button contrôle existe dans l’élément <ContentTemplate> d’un contrôle UpdatePanel). Là encore, l’élément PostBackTrigger peut spécifier n’importe quel contrôle enfant de n’importe quel contrôle UpdatePanel dans l’unité d’encapsulation actuelle.

<Informations de référence sur l’élément Triggers>

Descendants de balisage :

Tag Description
<asp:AsyncPostBackTrigger> Spécifie un contrôle et un événement qui entraîneront une mise à jour partielle de la page pour le UpdatePanel qui contient cette référence de déclencheur.
<asp:PostBackTrigger> Spécifie un contrôle et un événement qui entraînent une mise à jour de page complète (actualisation de page complète). Cette balise peut être utilisée pour forcer une actualisation complète lorsqu’un contrôle déclencherait sinon un rendu partiel.

Procédure pas à pas : Déclencheurs Inter-UpdatePanel

  1. Créez une page ASP.NET avec un objet ScriptManager défini pour activer le rendu partiel. Ajoutez deux UpdatePanels à cette page : dans la première, incluez un contrôle Label ( Label1 ) et deux contrôles Button ( Button1 et Button2 ). Button1 doit indiquer Cliquer pour mettre à jour à la fois et Button2 doit indiquer Cliquer pour mettre à jour ceci, ou quelque chose dans ce sens. Dans le deuxième UpdatePanel, incluez uniquement un contrôle Label ( Label2 ), mais définissez sa propriété ForeColor sur autre chose que la valeur par défaut pour la différencier.
  2. Définissez la propriété UpdateMode des deux balises UpdatePanel sur Conditionnel.

Listing 1 : Balisage pour default.aspx :



<%@ 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>

  1. Dans le gestionnaire d’événements Click pour Button1, définissez Label1.Text et Label2.Text sur un élément dépendant du temps (par exemple, DateTime.Now.ToLongTimeString()). Pour le gestionnaire d’événements Click pour Button2, définissez uniquement Label1.Text sur la valeur dépendante du temps.

Listing 2 : Codebehind (supprimé) dans default.aspx.cs :

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();
    }
}
  1. Appuyez sur F5 pour générer et exécuter le projet. Notez que lorsque vous cliquez sur Mettre à jour les deux panneaux, les deux étiquettes changent de texte ; Toutefois, lorsque vous cliquez sur Mettre à jour ce panneau, seule la mise à jour de Label1 est mise à jour.

Capture d’écran montrant le premier bouton qui indique Mettre à jour les deux panneaux et le deuxième bouton qui indique Mettre à jour ce panneau.

(Cliquez pour afficher l’image en taille réelle)

Sous le capot

En utilisant l’exemple que nous venons de construire, nous pouvons examiner ce que fait ASP.NET AJAX et comment nos déclencheurs de volets croisés UpdatePanel fonctionnent. Pour ce faire, nous allons utiliser le code HTML source de page généré, ainsi que l’extension Mozilla Firefox appelée FireBug. Avec elle, nous pouvons facilement examiner les publications AJAX. Nous utiliserons également l’outil Réflecteur .NET de Lutz Roeder. Ces deux outils sont disponibles gratuitement en ligne, et peuvent être trouvés avec une recherche sur Internet.

Un examen du code source de la page ne montre presque rien d’extraordinaire; Les contrôles UpdatePanel sont affichés en tant que <div> conteneurs, et nous pouvons voir les inclut dans la ressource de script fournie par .<asp:ScriptManager> Il existe également de nouveaux appels spécifiques à AJAX à PageRequestManager qui sont internes à la bibliothèque de scripts client AJAX. Enfin, nous voyons les deux conteneurs UpdatePanel, l’un avec les boutons rendus <input> avec les deux <asp:Label> contrôles affichés en tant que <span> conteneurs. (Si vous inspectez l’arborescence DOM dans FireBug, vous remarquerez que les étiquettes sont grisées pour indiquer qu’elles ne produisent pas de contenu visible).

Cliquez sur le bouton Mettre à jour ce panneau et notez que le UpdatePanel supérieur sera mis à jour avec l’heure actuelle du serveur. Dans FireBug, choisissez l’onglet Console pour pouvoir examiner la demande. Examinez d’abord les paramètres de requête POST :

Capture d’écran montrant une boîte de dialogue Firebug avec console sélectionnée.

(Cliquez pour afficher l’image en taille réelle)

Notez que updatePanel a indiqué au code AJAX côté serveur précisément l’arborescence de contrôle qui a été déclenchée via le paramètre ScriptManager1 : Button1 du UpdatePanel1 contrôle. Cliquez maintenant sur le bouton Mettre à jour les deux panneaux. Ensuite, en examinant la réponse, nous voyons une série de variables délimitées par un canal définie dans une chaîne ; Plus précisément, nous voyons que le top UpdatePanel, UpdatePanel1, a l’intégralité de son code HTML envoyé au navigateur. La bibliothèque de scripts client AJAX remplace le contenu HTML d’origine de UpdatePanel par le nouveau contenu via la .innerHTML propriété , ce qui permet au serveur d’envoyer le contenu modifié à partir du serveur au format HTML.

Cliquez maintenant sur le bouton Mettre à jour les deux panneaux et examinez les résultats du serveur. Les résultats sont très similaires : les deux UpdatePanels reçoivent un nouveau code HTML du serveur. Comme avec le rappel précédent, un état de page supplémentaire est envoyé.

Comme nous pouvons le voir, étant donné qu’aucun code spécial n’est utilisé pour effectuer une publication AJAX, la bibliothèque de scripts client AJAX est en mesure d’intercepter les publications de formulaire sans aucun code supplémentaire. Les contrôles serveur utilisent automatiquement JavaScript afin qu’ils n’envoient pas automatiquement le formulaire : ASP.NET injecte automatiquement du code pour la validation et l’état du formulaire, principalement grâce à l’inclusion automatique des ressources de script, à la classe PostBackOptions et à la classe ClientScriptManager.

Pour instance, envisagez un contrôle CheckBox ; examinez le désassemblement de classe dans .NET Reflector. Pour ce faire, assurez-vous que votre assembly System.Web est ouvert et accédez à la System.Web.UI.WebControls.CheckBox classe, en ouvrant la RenderInputTag méthode . Recherchez une condition qui vérifie la AutoPostBack propriété :

Capture d’écran montrant le code qui commence par sur Click equals.

(Cliquez pour afficher l’image en taille réelle)

Lorsque la publication automatique est activée sur un CheckBox contrôle (via la propriété AutoPostBack étant true), la balise résultante <input> est donc rendue avec un script de gestion d’événements ASP.NET dans son onclick attribut. L’interception de la soumission du formulaire permet ensuite d’injecter ASP.NET AJAX dans la page de manière non intrusive, ce qui permet d’éviter toute modification de rupture potentielle qui pourrait se produire en utilisant un remplacement de chaîne éventuellement imprécis. En outre, cela permet à tout contrôle de ASP.NET personnalisé d’utiliser la puissance de ASP.NET AJAX sans code supplémentaire pour prendre en charge son utilisation dans un conteneur UpdatePanel.

La <triggers> fonctionnalité correspond aux valeurs initialisées dans l’appel PageRequestManager à _updateControls (notez que la bibliothèque de scripts client AJAX ASP.NET utilise la convention selon laquelle les méthodes, les événements et les noms de champs qui commencent par un trait de soulignement sont marqués comme internes et ne sont pas destinés à être utilisés en dehors de la bibliothèque elle-même). Avec elle, nous pouvons observer quels contrôles sont destinés à provoquer des publications AJAX.

Par exemple, nous allons ajouter deux contrôles supplémentaires à la page, en laissant un contrôle en dehors des UpdatePanels entièrement et en laissant un contrôle dans un UpdatePanel. Nous allons ajouter un contrôle CheckBox dans le UpdatePanel supérieur et supprimer un DropDownList avec un certain nombre de couleurs définies dans la liste. Voici le nouveau balisage :

Listing 3 : Nouvelle marque de révision

<%@ 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="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" />
 <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 nouveau code-behind :

Listing 4: Codebehind

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 liste déroulante sélectionne l’une des trois couleurs pour afficher la deuxième étiquette, que la zone case activée détermine à la fois si elle est en gras et si les étiquettes affichent la date et l’heure. La zone case activée ne doit pas entraîner de mise à jour AJAX, mais la liste déroulante le doit, même si elle n’est pas hébergée dans un UpdatePanel.

Capture d’écran montrant un navigateur web appelé Page sans titre et une liste déroulante avec la couleur Bleu sélectionnée sous le bouton mettre à jour les deux panneaux.

(Cliquez pour afficher l’image en taille réelle)

Comme le montre la capture d’écran ci-dessus, le bouton le plus récent à cliquer était le bouton droit Mettre à jour ce panneau, qui a mis à jour l’heure supérieure indépendamment de l’heure inférieure. La date a également été désactivée entre les clics, car la date est visible dans l’étiquette du bas. Enfin, la couleur du bas de l’étiquette est intéressante : elle a été mise à jour plus récemment que le texte de l’étiquette, ce qui montre que l’état de contrôle est important et que les utilisateurs s’attendent à ce qu’il soit conservé via les publications AJAX. Toutefois, l’heure n’a pas été mise à jour. L’heure a été automatiquement remplie par le biais de la persistance du champ __VIEWSTATE de la page interprétée par le runtime ASP.NET lorsque le contrôle était réinitulé sur le serveur. Le code ASP.NET serveur AJAX ne reconnaît pas les méthodes dans lesquelles les contrôles changent d’état ; il remplit simplement à nouveau à partir de l’état d’affichage, puis exécute les événements appropriés.

Il convient toutefois de souligner que si j’avais initialisé l’heure dans l’événement Page_Load, l’heure aurait été incrémentée correctement. Par conséquent, les développeurs doivent se méfier que le code approprié est exécuté pendant les gestionnaires d’événements appropriés et éviter d’utiliser Page_Load lorsqu’un gestionnaire d’événements de contrôle est approprié.

Résumé

Le contrôle UpdatePanel ASP.NET extensions AJAX est polyvalent et peut utiliser un certain nombre de méthodes pour identifier les événements de contrôle qui doivent entraîner sa mise à jour. Il prend en charge la mise à jour automatique par ses contrôles enfants, mais peut également répondre aux événements de contrôle ailleurs dans la page.

Pour réduire le risque de charge de traitement du serveur, il est recommandé que la ChildrenAsTriggers propriété d’un UpdatePanel soit définie falsesur , et que les événements soient activés au lieu d’être inclus par défaut. Cela empêche également les événements inutiles de provoquer des effets potentiellement indésirables, notamment la validation et les modifications apportées aux champs d’entrée. Ces types de bogues peuvent être difficiles à isoler, car la page est mise à jour de manière transparente pour l’utilisateur, et la cause peut donc ne pas être immédiatement évidente.

En examinant le fonctionnement interne du modèle de ASP.NET formulaire AJAX après l’interception, nous avons pu déterminer qu’il utilise le framework déjà fourni par ASP.NET. Ce faisant, il conserve une compatibilité maximale avec les contrôles conçus à l’aide de la même infrastructure et s’intruse au minimum sur tout code JavaScript supplémentaire écrit pour la page.

Bio

Rob Paveza est développeur d’applications .NET senior chez Terralever (www.terralever.com), une société de marketing interactive de premier plan à Tempe, en AZ. Il est accessible à l’adresse robpaveza@gmail.com, et son blog se trouve à l’adresse http://geekswithblogs.net/robp/.

Scott Cate travaille avec les technologies web Microsoft depuis 1997 et est président de myKB.com (www.myKB.com) où il se spécialise dans l’écriture d’applications ASP.NET basées sur des solutions de base de connaissances. Scott peut être contacté par e-mail à l’adresse scott.cate@myKB.com ou son blog à ScottCate.com