Freigeben über


Erstellen von benutzerdefinierten Clientereignissen

Aktualisiert: November 2007

Die AJAX-Funktionalität in ASP.NET umfasst ein vollständiges vielschichtiges Clientereignismodell. Die Sys.Application-Klasse stellt Ereignisse auf Anwendungsebene bereit. Die Sys.WebForms.PageRequestManager-Klasse stellt Ereignisse für die Teile der Seite bereit, die beim Teilrendering der Seite aktualisiert werden. Einzelne Komponenten, wie Steuerelemente und Verhalten, verfügen über eigene Ereignisse. Weitere Informationen zu diesen Ereignissen finden Sie unter Lebenszyklusereignisse des AJAX-Clients.

Mit ASP.NET können Sie auch dem Clientlebenszyklus Ereignisse hinzufügen. Mit der Sys.UI.DomEvent-Klasse können Sie HTML-DOM (Document Object Model)-Ereignisse an benutzerdefinierte ASP.NET AJAX-Komponenten binden. Außerdem kann die Sys.EventHandlerList-Klasse zum direkten Erstellen von neuen ASP.NET AJAX-Clientereignissen verwendet werden.

Anfügen an DOM-Ereignisse

In vielen Fällen sind für Ereignisse, mit denen Sie arbeiten möchten, im HTML-DOM entsprechende Ereignisse definiert. Beispielsweise kann ein benutzerdefiniertes Schaltflächen-Steuerelement in ASP.NET AJAX das click-Ereignis des <button>-HTML-Elements verwenden, an das es angefügt ist. Die addHandler-Methode der DomEvent-Klasse kann verwendet werden, um ein DOM-Ereignis an eine ASP.NET AJAX-Anwendung oder eine benutzerdefinierte Komponente zu binden, wie im folgenden Beispiel gezeigt:

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

Sie können auch die Verknüpfung $ addHandler verwenden, wie im folgenden Beispiel gezeigt:

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

Die addHandler-Methode akzeptiert drei Parameter: element, eventName und handler. Der element-Parameter ist ein Verweis auf das DOM-Element, mit dem das Ereignis bereitgestellt wird. Der eventName-Parameter ist der Name des DOM-Ereignisses. Der handler-Parameter ist ein Verweis auf die Funktion, die beim Auslösen des Ereignisses aufgerufen wird. Weitere Informationen finden Sie unter Sys.UI.DomEvent addHandler-Methode.

Rufen Sie die Sys.UI.DomEvent.removeHandler-Methode oder die Verknüpfung $removeHandler auf, wenn Sie einen Handler für ein DOM-Ereignis entfernen möchten. An diese Methode werden die gleichen Parameter übergeben wie an addHandler.

Hinweis:

Ereignisnamen, die an die addHandler-Funktion und an die removeHandler-Funktion übergeben werden, sollten nicht das Präfix "on" enthalten. Beispielsweise sollte "click" statt "onclick" verwendet werden.

Hinzufügen und Entfernen von benutzerdefinierten Ereignishandlern

Mit der addHandler-Methode der Sys.EventHandlerList-Klasse können Sie einem Ereignis einer benutzerdefinierten ASP.NET AJAX-Komponente einen neuen Ereignishandler hinzufügen. Im ASP.NET AJAX-Ereignismodell werden alle Clientereignisse und die entsprechenden Ereignishandler in einem EventHandlerList-Objekt gespeichert, das ein für diesen Zweck angelegtes Spezialwörterbuch darstellt. Jede Komponente, einschließlich dem aktuellen Application-Objekt, verfügt über eine eigene EventHandlerList-Instanz. Durch das Hinzufügen eines Elements zum EventHandlerList-Objekt wird der entsprechenden Komponente ein neues Ereignis und ein neuer Ereignishandler hinzugefügt. Ereignisse werden mit der folgenden Syntax hinzugefügt:

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

Die events-Eigenschaft der Sys.Component-Klasse gibt die EventHandlerList-Instanz für diese Komponente zurück. Die events-Eigenschaft wird von den Klassen Sys.UI.Control, Sys.UI.Behavior und Sys.Application geerbt. Der event-Parameter ist der Name des neuen oder vorhandenen Ereignisses, für das ein Handler hinzugefügt wird. Der handler-Parameter ist ein Verweis auf die Funktion, die beim Auslösen des Ereignisses aufgerufen wird. Wird der event-Parameter auf einen neuen Wert festgelegt, wird dem Wörterbuch ein neues Ereignis hinzugefügt.

Ein benutzerdefiniertes Ereignis kann aus dem Wörterbuch entfernt werden, indem die removeHandler-Methode der Sys.EventHandlerList-Klasse aufgerufen wird, die die gleichen Parameter wie addHandler akzeptiert.

Um Handler zu Ereignissen hinzuzufügen, die bereits inMicrosoft AJAX Library definiert sind, wird der add_-Accessor des Ereignisses verwendet, wie im folgenden Beispiel gezeigt:

Sys.Application.add_load(myLoadHandler);

Auslösen von benutzerdefinierten Ereignissen

Mit der getHandler-Methode der EventHandlerList-Instanz kann ein benutzerdefiniertes Ereignis ausgelöst werden. Der Ereignisname wird dabei als Parameter übergeben. Diese Methode gibt eine Funktion zurück, die alle Handlerfunktionen dieses Ereignisses aggregiert. Rufen Sie zum Auslösen des Ereignisses die zurückgegebene Funktion auf, wie in folgendem Beispiel gezeigt:

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

Gemäß der Konvention akzeptieren Ereignishandler zwei Parameter: sender und eventArgs. Der Absender ist die Komponente, auf die sich das Ereignis bezieht, in der Regel this. Der eventArgs-Parameter verweist auf ein Sys.EventArgs-Objekt. Dieses Objekt kann Informationen (beispielsweise Mauskoordinaten) enthalten, die an das Ereignis übergeben werden. Die Parameter sender und eventArgs müssen nicht angegeben werden, wenn die Signatur der Funktion, die von getHandler zurückgegeben wird, der Signatur von allen anderen zugeordneten Handlerfunktionen entspricht Es wird jedoch empfohlen, diese Parameter anzugeben, wie im Beispiel zuvor gezeigt.

Beispiel

Beschreibung

Im folgenden Beispiel wird ein einfacher Multiple-Choice-Test mit zwei Abschnitten erstellt. Wenn alle Fragen in einem Abschnitt beantwortet wurden, wird die Hintergrundfarbe des Abschnitts geändert. Wenn die Benutzer auf die Schaltfläche am Ende des Tests klicken, wird neben jeder Frage eine Statusmeldung angezeigt, die angibt, ob die Antwort richtig ist.

Die Anwendung enthält Instanzen von zwei benutzerdefinierten Steuerelementen. Das Question-Steuerelement ist an ein <select>-HTML-Element angefügt. Das Section-Steuerelement ist an ein <div>-Element angefügt, dass mindestens ein Question-Steuerelement enthält. Das Question-Steuerelement stellt ein select-Ereignis bereit, das an das onChange-Ereignis des zugrunde liegenden <select>-Elements mithilfe einer Sys.UI.DomEvent-Instanz gebunden ist. Das Section-Steuerelement stellt ein complete-Ereignis bereit, das von einer benutzerdefinierten Funktion ausgelöst wird, wenn alle Question-Steuerelemente der Section-Instanz beantwortet wurden.

Code

Im folgenden Beispiel wird die Seite Default.aspx dargestellt, mit der die Komponenteninstanzen erstellt und die Ereignisse behandelt werden.

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

Im folgenden Beispiel wird die Datei Question.js dargestellt, in der das Demo.Question-Steuerelement definiert ist.

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();

Im folgenden Beispiel wird die Datei Section.js dargestellt, in der das Demo.Section-Steuerelement definiert ist.

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();

Siehe auch

Aufgaben

Erstellen benutzerdefinierter AJAX-Clientsteuerelemente

Referenz

Sys.Application-Klasse

Sys.WebForms.PageRequestManager-Klasse

Sys.UI.DomEvent-Klasse

Sys.EventHandlerList-Klasse