Partager via


Création d'événements clients personnalisés

Mise à jour : novembre 2007

Les fonctionnalités AJAX d'ASP.NET incluent un modèle d'événement client complet superposé en couches. La classe Sys.Application fournit des événements au niveau application. La classe Sys.WebForms.PageRequestManager fournit des événements qui ont rapport aux parties de la page impliquées dans un rendu de page partielle. Les composants individuels, tels que les contrôles et les comportements, ont leurs propres événements. Pour plus d'informations sur ces événements, consultez Événements de cycle de vie client AJAX.

ASP.NET vous permet également d'ajouter des événements au cycle de vie client. La classe Sys.UI.DomEvent vous permet de lier des événements DOM (Document Object Model) HTML aux composants personnalisés ASP.NET AJAX. De plus, la classe Sys.EventHandlerList vous permet de créer directement de nouveaux événements clients ASP.NET AJAX.

Éléments attachés aux événements DOM

Dans de nombreux cas, un événement avec lequel vous souhaitez travailler correspond à un événement défini dans le DOM HTML. Par exemple, un contrôle bouton personnalisé ASP.NET AJAX peut utiliser l'événement click de l'élément HTML <button> auquel il est attaché. Pour lier un événement DOM à une application ou un composant personnalisé ASP.NET AJAX, vous utilisez la méthode addHandler de la classe DomEvent, comme illustré dans l'exemple suivant :

Sys.UI.DomEvent.addHandler(element, 'click', this.myClickHandler);

Vous pouvez également utiliser le raccourci $addHandler, comme illustré dans l'exemple suivant :

$addHandler(element, 'click', this.myClickHandler);

La méthode addHandler prend trois paramètres : element, eventName et handler. Le paramètre element est une référence à l'élément DOM qui expose l'événement. Le paramètre eventName est le nom de l'événement DOM lui-même. Le paramètre handler est une référence à la fonction à appeler lorsque l'événement est déclenché. Pour plus d'informations, consultez addHandler, méthode de Sys.UI.DomEvent.

Pour supprimer le gestionnaire d'un événement DOM, vous appelez la méthode Sys.UI.DomEvent.removeHandler ou le raccourci $removeHandler, en passant les mêmes paramètres que pour addHandler.

Remarque :

Les noms d'événements passés aux fonctions addHandler et removeHandler ne doivent pas inclure le préfixe « on ». Par exemple, utilisez « click », pas « onclick ».

Ajout et suppression de gestionnaires d'événements personnalisés

Pour ajouter un nouveau gestionnaire d'événements pour un événement d'un composant personnalisé ASP.NET AJAX, utilisez la méthode addHandler de la classe Sys.EventHandlerList. Tous les événements clients et les gestionnaires d'événements associés dans le modèle d'événement ASP.NET AJAX sont stockés dans un objet EventHandlerList, qui constitue un dictionnaire spécialisé à cet effet. Chaque composant, y compris l'objet Application actuel, a sa propre instance de EventHandlerList. En ajoutant un élément à l'objet EventHandlerList, vous ajoutez un nouvel événement et un gestionnaire d'événements au composant associé. Ajoutez des événements en utilisant la syntaxe suivante :

this.get_events().addHandler(event, handler);

La propriété events de la classe Sys.Component retourne l'instance EventHandlerList de ce composant. La propriété events est héritée par les classes Sys.UI.Control, Sys.UI.Behavior et Sys.Application. Le paramètre event est le nom du nouvel événement ou de l'événement existant auquel un gestionnaire doit être ajouté. Le paramètre handler est une référence à la fonction à appeler lorsque l'événement est déclenché. En donnant une nouvelle valeur au paramètre event, vous ajoutez un nouvel événement au dictionnaire.

Pour supprimer un événement personnalisé du dictionnaire, vous utilisez la méthode removeHandler de la classe Sys.EventHandlerList, qui prend les mêmes paramètres que addHandler.

Pour ajouter des gestionnaires aux événements qui sont déjà définis dans Microsoft AJAX Library, utilisez l'accesseur add_ pour cet événement, comme dans l'exemple suivant :

Sys.Application.add_load(myLoadHandler);

Déclenchement d'événements personnalisés

Pour déclencher un événement personnalisé, appelez la méthode getHandler de l'instance EventHandlerList, en passant le nom de l'événement sous forme de paramètre. Cette méthode retourne une fonction qui regroupe toutes celles qui constituent des gestionnaires pour cet événement. Appelez la fonction retournée pour déclencher l'événement, comme dans l'exemple suivant :

var h = this.get_events().getHandler('myCustomEvent')
if (h) h(this, Sys.EventArgs.Empty);

Par convention, les gestionnaires d'événements prennent deux paramètres : sender et eventArgs. L'expéditeur est le composant à qui l'événement s'applique, en général this. Le paramètre eventArgs fait référence à un objet Sys.EventArgs. Cet objet peut contenir des informations passées à l'événement, telles que les coordonnées de la souris. Vous pouvez omettre les paramètres sender et eventArgs, tant que la signature de la fonction a retournée getHandler correspond à celle de toutes les fonctions gestionnaire associées. Toutefois, il est recommandé d'inclure les paramètres, comme dans l'exemple illustré précédemment.

Exemple

Description

L'exemple suivant crée un simple questionnaire à choix multiple contenant deux sections. Lorsque toutes les questions dans une section ont une réponse, la couleur d'arrière-plan de la section change. Lorsque l'utilisateur clique sur le bouton à la fin du test, un message d'état à côté de chaque question indique si la réponse est correcte.

L'application inclut des instances de deux contrôles personnalisés. Le contrôle Question est attaché à un élément HTML <select> et le contrôle Section à un élément <div> qui contient un ou plusieurs contrôles Question. Le contrôle Question expose un événement select, lié à l'événement onChange de l'élément <select> sous-jacent par une instance de Sys.UI.DomEvent. Le contrôle Section expose un événement complete déclenché par une fonction définie par l'utilisateur lorsque tous les contrôles Question dans l'instance Section ont une réponse.

Code

L'exemple suivant affiche la page Default.aspx qui crée les instances de composant et gère les événements.

<%@ Page Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" >
    <title>Custom Events Example</title>
</head>
<body>
<form id="form1" >
    <asp:ScriptManager ID="ScriptManager1"  >
        <Scripts>
           <asp:ScriptReference Path="question.js" />
           <asp:ScriptReference Path="section.js" />
       </Scripts>
    </asp:ScriptManager>
    <script type="text/javascript">
    // Add handler to init event
    Sys.Application.add_init(appInitHandler);

    function appInitHandler() {
      // create components
      $create(Demo.Question, {correct: '3'},
        {select: onAnswer},null, $get('Question1'));
      $create(Demo.Question, {correct: '3'},
        {select: onAnswer},null, $get('Question2'));
      $create(Demo.Question, {correct: '3'},
        {select: onAnswer},null, $get('Question3'));
      $create(Demo.Question, {correct: '3'},
        {select: onAnswer},null, $get('Question4'));
      $create(Demo.Section, null,
        {complete: onSectionComplete},null, $get('group1'));
      $create(Demo.Section, null,
        {complete: onSectionComplete},null, $get('group2'));
    }

    function onAnswer(question) {
        // If all questions in this section answered, 
        // raise complete event
        var section = question.get_element().parentElement;
        var questions = section.children;
        $get(question.get_id() + 'Status').innerHTML = '';
        for (var i=0; i<questions.length; i++) {
            if (questions[i].selectedIndex === -1) {
                return;
            }
        }
        $find(section.id).raiseComplete();
    }

    function onSectionComplete(section) {
        // Change background color of <div>.
        section.get_element().style.backgroundColor = 'yellow';
    }

    function done() {
        // Display correct answers where needed.
        var c = Sys.Application.getComponents();
        for (var i=0; i<c.length; i++) {
            var type = Object.getType(c[i]).getName();
            if (type !== 'Demo.Question') continue;
            var element = c[i].get_element();
            var answer = element.selectedIndex;
            var correct = $find(c[i].get_id()).get_correct();
            var statusElement = c[i].get_id() + 'Status';
            if (answer !== correct) {
                $get(statusElement).innerHTML = 'Incorrect. Try again.';
            }
            else
            {
                $get(statusElement).innerHTML = 'Correct.';
            }
        }
    }

    function resethandler() {
        var c = Sys.Application.getComponents();
        for (var i=0; i<c.length; i++) {
            var type = Object.getType(c[i]).getName();
            if (type === 'Demo.Question') {
                var element = c[i].get_element();
                element.selectedIndex = -1;
                var answer = element.selectedIndex;
                var statusElement = c[i].get_id() + 'Status';
                $get(statusElement).innerHTML = '';
            }
            else if (type === 'Demo.Section') {
                c[i].get_element().style.backgroundColor = 'White';

            }
        }
    }
    </script>
    <h3>Addition</h3><br />
    <div id="Group1">
        2 + 2 = 
        <select id="Question1">
            <option>2</option>
            <option>22</option>
            <option>4</option>
            <option>5</option>
        </select><span id="Question1Status"></span><br />
        2 + 3 = 
        <select id="Question2" >
            <option>3</option>
            <option>23</option>
            <option>5</option>
            <option>6</option>
        </select><span id="Question2Status"></span><br />
    </div><br /> <br />   
    <h3>Subtraction</h3><br />
    <div id="Group2">
        2 - 1 = 
        <select id="Question3" >
            <option>2</option>
            <option>0</option>
            <option>1</option>
            <option>-2</option>
        </select><span id="Question3Status"></span><br />
        2 - 2 = 
        <select id="Question4" >
            <option>2</option>
            <option>-2</option>
            <option>0</option>
            <option>-4</option>
        </select><span id="Question4Status"></span><br />
    </div><br /><br />
    <input id="Submit1" type="button" value="Check Answers" onclick="done()" />
    <input id="Reset1" type="button" value="Start Again" onclick="resethandler()" />
</form>
</body>
</html>
<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" >
    <title>Custom Events Example</title>
</head>
<body>
<form id="form1" >
    <asp:ScriptManager ID="ScriptManager1"  >
        <Scripts>
           <asp:ScriptReference Path="question.js" />
           <asp:ScriptReference Path="section.js" />
       </Scripts>
    </asp:ScriptManager>
    <script type="text/javascript">
    // Add handler to init event
    Sys.Application.add_init(appInitHandler);

    function appInitHandler() {
      // create components
      $create(Demo.Question, {correct: '3'},
        {select: onAnswer},null, $get('Question1'));
      $create(Demo.Question, {correct: '3'},
        {select: onAnswer},null, $get('Question2'));
      $create(Demo.Question, {correct: '3'},
        {select: onAnswer},null, $get('Question3'));
      $create(Demo.Question, {correct: '3'},
        {select: onAnswer},null, $get('Question4'));
      $create(Demo.Section, null,
        {complete: onSectionComplete},null, $get('group1'));
      $create(Demo.Section, null,
        {complete: onSectionComplete},null, $get('group2'));
    }

    function onAnswer(question) {
        // If all questions in this section answered, 
        // raise complete event
        var section = question.get_element().parentElement;
        var questions = section.children;
        $get(question.get_id() + 'Status').innerHTML = '';
        for (var i=0; i<questions.length; i++) {
            if (questions[i].selectedIndex === -1) {
                return;
            }
        }
        $find(section.id).raiseComplete();
    }

    function onSectionComplete(section) {
        // Change background color of <div>.
        section.get_element().style.backgroundColor = 'yellow';
    }

    function done() {
        // Display correct answers where needed.
        var c = Sys.Application.getComponents();
        for (var i=0; i<c.length; i++) {
            var type = Object.getType(c[i]).getName();
            if (type !== 'Demo.Question') continue;
            var element = c[i].get_element();
            var answer = element.selectedIndex;
            var correct = $find(c[i].get_id()).get_correct();
            var statusElement = c[i].get_id() + 'Status';
            if (answer !== correct) {
                $get(statusElement).innerHTML = 'Incorrect. Try again.';
            }
            else
            {
                $get(statusElement).innerHTML = 'Correct.';
            }
        }
    }

    function resethandler() {
        var c = Sys.Application.getComponents();
        for (var i=0; i<c.length; i++) {
            var type = Object.getType(c[i]).getName();
            if (type === 'Demo.Question') {
                var element = c[i].get_element();
                element.selectedIndex = -1;
                var answer = element.selectedIndex;
                var statusElement = c[i].get_id() + 'Status';
                $get(statusElement).innerHTML = '';
            }
            else if (type === 'Demo.Section') {
                c[i].get_element().style.backgroundColor = 'White';

            }
        }
    }
    </script>
    <h3>Addition</h3><br />
    <div id="Group1">
        2 + 2 = 
        <select id="Question1">
            <option>2</option>
            <option>22</option>
            <option>4</option>
            <option>5</option>
        </select><span id="Question1Status"></span><br />
        2 + 3 = 
        <select id="Question2" >
            <option>3</option>
            <option>23</option>
            <option>5</option>
            <option>6</option>
        </select><span id="Question2Status"></span><br />
    </div><br /> <br />   
    <h3>Subtraction</h3><br />
    <div id="Group2">
        2 - 1 = 
        <select id="Question3" >
            <option>2</option>
            <option>0</option>
            <option>1</option>
            <option>-2</option>
        </select><span id="Question3Status"></span><br />
        2 - 2 = 
        <select id="Question4" >
            <option>2</option>
            <option>-2</option>
            <option>0</option>
            <option>-4</option>
        </select><span id="Question4Status"></span><br />
    </div><br /><br />
    <input id="Submit1" type="button" value="Check Answers" onclick="done()" />
    <input id="Reset1" type="button" value="Start Again" onclick="resethandler()" />
</form>
</body>
</html>

L'exemple suivant affiche le fichier Question.js qui définit le contrôle Demo.Question.

Type.registerNamespace("Demo");

// Constructor
Demo.Question = function(element) {

    Demo.Question.initializeBase(this, [element]);

    // Create a delegate for the select event.
    this._selectDelegate = null;
}
Demo.Question.prototype = {

    // correct property accessors
    get_correct: function() {
        return this.get_element().name - 1;
    },
    set_correct: function(value) {
        this.get_element().name = value;
    },

    // Bind and unbind to select event.
    add_select: function(handler) {
        this.get_events().addHandler('select', handler);
    },
    remove_select: function(handler) {
        this.get_events().removeHandler('select', handler);
    },

    // Release resources before control is disposed.
    dispose: function() {

        var element = this.get_element();

        if (this._selectDelegate) {
            $clearHandlers(element);
            delete this._selectDelegate;
        }

        Demo.Question.callBaseMethod(this, 'dispose');
    },

    initialize: function() {

        var element = this.get_element();

        // Make sure no option is selected.
        element.value = ""; 

        // Attach delegate to select event.
        if (this._selectDelegate === null) {
            this._selectDelegate = Function.createDelegate(this, this._selectHandler);
        }
        Sys.UI.DomEvent.addHandler(element, 'change', this._selectDelegate);

        Demo.Question.callBaseMethod(this, 'initialize');

    },

    _selectHandler: function(event) {
        var h = this.get_events().getHandler('select');
        if (h) h(this, Sys.EventArgs.Empty);
    }
}
Demo.Question.registerClass('Demo.Question', Sys.UI.Control);

// Since this script is not loaded by System.Web.Handlers.ScriptResourceHandler
// invoke Sys.Application.notifyScriptLoaded to notify ScriptManager 
// that this is the end of the script.
if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
Type.registerNamespace("Demo");

// Constructor
Demo.Question = function(element) {

    Demo.Question.initializeBase(this, [element]);

    // Create a delegate for the select event.
    this._selectDelegate = null;
}
Demo.Question.prototype = {

    // correct property accessors
    get_correct: function() {
        return this.get_element().name - 1;
    },
    set_correct: function(value) {
        this.get_element().name = value;
    },

    // Bind and unbind to select event.
    add_select: function(handler) {
        this.get_events().addHandler('select', handler);
    },
    remove_select: function(handler) {
        this.get_events().removeHandler('select', handler);
    },

    // Release resources before control is disposed.
    dispose: function() {

        var element = this.get_element();

        if (this._selectDelegate) {
            $clearHandlers(element);
            delete this._selectDelegate;
        }

        Demo.Question.callBaseMethod(this, 'dispose');
    },

    initialize: function() {

        var element = this.get_element();

        // Make sure no option is selected.
        element.value = ""; 

        // Attach delegate to select event.
        if (this._selectDelegate === null) {
            this._selectDelegate = Function.createDelegate(this, this._selectHandler);
        }
        Sys.UI.DomEvent.addHandler(element, 'change', this._selectDelegate);

        Demo.Question.callBaseMethod(this, 'initialize');

    },

    _selectHandler: function(event) {
        var h = this.get_events().getHandler('select');
        if (h) h(this, Sys.EventArgs.Empty);
    }
}
Demo.Question.registerClass('Demo.Question', Sys.UI.Control);

// Since this script is not loaded by System.Web.Handlers.ScriptResourceHandler
// invoke Sys.Application.notifyScriptLoaded to notify ScriptManager 
// that this is the end of the script.
if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();

L'exemple suivant affiche le fichier Section.js qui définit le contrôle Demo.Section.

Type.registerNamespace("Demo");

// Constructor
Demo.Section = function(element) {

    Demo.Section.initializeBase(this, [element]);
}
Demo.Section.prototype = {

    // Create add and remove accessors fot the complete event.
    add_complete: function(handler) {
        this.get_events().addHandler("complete", handler);
    },
    remove_complete: function(handler) {
        this.get_events().removeHandler("complete", handler);
    },

    // Create a function to raise the complete event.
    raiseComplete: function() {
        var h = this.get_events().getHandler('complete');
        if (h) h(this);
    },

    // Release resources before control is disposed.
    dispose: function() {
        var element = this.get_element();
        $clearHandlers(element);
        Demo.Section.callBaseMethod(this, 'dispose');
    }
}
Demo.Section.registerClass('Demo.Section', Sys.UI.Control);

// Since this script is not loaded by System.Web.Handlers.ScriptResourceHandler
// invoke Sys.Application.notifyScriptLoaded to notify ScriptManager 
// that this is the end of the script.
if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
Type.registerNamespace("Demo");

// Constructor
Demo.Section = function(element) {

    Demo.Section.initializeBase(this, [element]);
}
Demo.Section.prototype = {

    // Create add and remove accessors fot the complete event.
    add_complete: function(handler) {
        this.get_events().addHandler("complete", handler);
    },
    remove_complete: function(handler) {
        this.get_events().removeHandler("complete", handler);
    },

    // Create a function to raise the complete event.
    raiseComplete: function() {
        var h = this.get_events().getHandler('complete');
        if (h) h(this);
    },

    // Release resources before control is disposed.
    dispose: function() {
        var element = this.get_element();
        $clearHandlers(element);
        Demo.Section.callBaseMethod(this, 'dispose');
    }
}
Demo.Section.registerClass('Demo.Section', Sys.UI.Control);

// Since this script is not loaded by System.Web.Handlers.ScriptResourceHandler
// invoke Sys.Application.notifyScriptLoaded to notify ScriptManager 
// that this is the end of the script.
if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();

Voir aussi

Tâches

Création de contrôles clients AJAX personnalisés

Référence

Sys.Application, classe

Sys.WebForms.PageRequestManager, classe

Sys.UI.DomEvent, classe

Sys.EventHandlerList, classe