Erstellen von benutzerdefinierten nicht visuellen Clientkomponenten
Aktualisiert: November 2007
In diesem Thema wird gezeigt, wie Sie eine nicht visuelle AJAX-Clientkomponente in ASP.NET erstellen, die von der Sys.Component-Basisklasse des Clients abgeleitet wird, und wie Sie diese Komponente in einer Seite verwenden.
In diesem Lernprogramm erfahren Sie, wie Sie folgende Aktionen ausführen:
Verwenden des Prototypentwurfsmusters zum Definieren einer nicht visuellen Komponentenklasse in ECMAScript (JavaScript).
Registrieren einer nicht visuellen Komponente als eine von der Component-Basisklasse abgeleitete Klasse.
Initialisieren der Component-Basisklasse der nicht visuellen Komponente und Aufrufen ihrer Methoden.
Erstellen von Eigenschaften, die eine Änderungsbenachrichtigung auslösen.
Verwenden der Komponente in einer Seite und Binden an die Ereignisse der Komponente.
Die Übersicht enthält ein Beispiel für einen Zeitgeber als nicht visuelle Clientkomponente. Der Zeitgeber löst Ereignisse aus, die Sie behandeln können.
In diesem Thema werden in erster Linie nicht visuelle komponentenbasierte Clientobjekte erläutert. Diese Komponenten sind von Component abgeleitet und werden normalerweise nicht auf der Benutzeroberfläche dargestellt. Es gibt zwei weitere Typen von ASP.NET AJAX-Clientkomponentenobjekten, die die Funktionalität der Basiskomponente erweitern: Verhalten, die von Sys.UI.Behavior abgeleitet werden, und Steuerelemente, die von Sys.UI.Control abgeleitet werden. In der folgenden Tabelle sind die Unterschiede zwischen Komponenten, Verhalten und Steuerelementen zusammengefasst.
Clientkomponenten-Objekttypen |
Zusammenfassung |
---|---|
Komponenten |
|
Verhalten |
|
Steuerelemente |
|
Vorbereitungsmaßnahmen
Um das Beispiel in diesem Thema auszuführen, benötigen Sie folgendes:
- Eine AJAX-fähige ASP.NET-Website. Wenn Sie bereits eine Website konfiguriert haben, können Sie diese für dieses Beispiel verwenden. Informationen zum Erstellen eines virtuellen Verzeichnisses oder einer Site finden Sie unter Gewusst wie: Erstellen und Konfigurieren von virtuellen Verzeichnissen in IIS 5.0 und 6.0.
Erstellen der grundlegenden Funktionalität einer nicht visuellen Clientkomponente
Eine nicht visuelle ASP.NET-AJAX-Clientkomponente kapselt JavaScript-Code, der in unterschiedlichen Anwendungen wiederverwendbar sein soll. Ein Beispiel für eine nicht visuelle Komponente ist eine Zeitgeberkomponente, die in festgelegten Intervallen Ereignisse auslöst.
Durch Ableitung von der Component-Basisklasse erbt die benutzerdefinierte Komponente automatisch die folgenden Features:
Ein browserübergreifendes Modell, um Handlerbindungen an Clientobjektereignisse zu verwalten.
Automatische Registrierung der Komponente in der Clientanwendung als verwerfbares Objekt, das die Sys.IDisposable-Schnittstelle implementiert.
Die Möglichkeit, Benachrichtigungsereignisse auszulösen, wenn Eigenschaften geändert werden.
Die Möglichkeit zum Ausführen einer Batchverarbeitung von Komponenteneigenschafteneinstellungen. Auf diese Weise fällt weniger Skriptumfang und Bearbeitungszeit an, als wenn sämtliche Logik in einzelnen get- und set-Accessoren der Eigenschaft behandelt wird.
Ein Überschreiben der Sys.Component.initialize-Methode zur Initialisierung beliebiger Eigenschaften und Ereignislistener.
Implementieren einer von der Komponentenklasse abgeleiteten Clientkomponente
Gehen Sie folgendermaßen vor, um eine benutzerdefinierte von Component abgeleitete Clientkomponente zu implementieren:
Definieren Sie eine Komponentenklasse mithilfe des Prototypentwurfsmusters.
Initialisieren Sie die Component-Basisinstanz der Komponente.
Machen Sie alle Eigenschaftenaccessoren verfügbar, und lösen Sie wahlweise ein propertyChanged-Benachrichtigungsereignis aus.
Überschreiben Sie die Dispose-Methode zum Freigeben von Ressourcen, z. B. Löschen von Ereignishandlern.
Die folgenden Abschnitte enthalten ausführliche Informationen über die Implementierungsschritte.
Definieren einer Komponentenklasse mithilfe des Prototypentwurfsmusters
Eine ASP.NET-AJAX-Clientklasse, die eine Komponentenklasse enthält, wird in JavaScript mithilfe des Prototypentwurfsmusters definiert. Um eine Komponentenklasse mithilfe des Prototypentwurfsmusters zu definieren, gehen Sie folgendermaßen vor:
Registrieren Sie den Namespace für die Komponentenklasse.
Erstellen Sie die Konstruktorfunktion für die Komponente, definieren Sie in der Konstruktorfunktion alle privaten Felder, und legen Sie deren Anfangswerte fest.
Definieren Sie den Prototyp der Komponente.
Registrieren Sie die Komponentenfunktion als eine Klasse, die von Component abgeleitet wird.
Weitere Informationen finden Sie unter Erstellen einer Clientkomponentenklasse mit dem Prototypmodell.
Initialisieren der Basisklasse
Rufen Sie in der Konstruktorfunktion der Komponente die geerbte Type.initializeBase-Methode auf, um den Basistyp der registrierten Klasse zu initialisieren. Eine nicht visuelle Komponentenklasse wird als Klasse registriert, die über einen Basistyp von Component verfügt. Nach dem Initialisieren der Component-Basisklasse sind deren Methoden für die Komponente verfügbar, und die Komponente wird automatisch als verwerfbares Objekt mit der AJAX-fähigen ASP.NET-Anwendung registriert. Weitere Informationen finden Sie unter Sys.IDisposable-Schnittstelle.
Jede Komponentenklasse, die von Component abgeleitet ist, muss seine Basisklasse im Konstruktor initialisieren. Normalerweise rufen Sie initializeBase auf, bevor im Konstruktor weiterer Code ausgeführt wird. Im folgenden Beispiel wird die Konstruktorfunktion einer nicht visuellen, von Component abgeleiteten Komponente veranschaulicht.
Samples.SimpleComponent = function()
{
Samples.SimpleComponent.initializeBase(this);
}
Definieren von Eigenschaften und Auslösen von Benachrichtigungen zu Eigenschaftenänderungen
Eigenschaften werden in der Komponentenklasse definiert. Diese Eigenschaften können von Seitenentwicklern abgerufen und festgelegt werden. Eine von Component abgeleitete ASP.NET-AJAX-Komponente erbt die Sys.Component.raisePropertyChanged-Methode, die Sie aufrufen, um ein propertyChanged-Ereignis für die Eigenschaften der Komponente auszulösen. Seitenentwickler, die die Komponente verwenden, können dann Bindungen an diese Ereignisse herstellen. Weitere Informationen finden Sie unter Definieren von benutzerdefinierten Komponenteneigenschaften und Auslösen von PropertyChanged-Ereignissen.
Initialisieren von Eigenschaften und Ereignislistenern
Wenn die benutzerdefinierte Komponente Eigenschaften oder Eventlistener initialisieren muss, sollten Sie die Sys.Component.initialize-Methode im Prototyp der Komponente überschreiben. Beispielsweise weist eine nicht visuelle Komponente, die von Component abgeleitet wird, einem Ereignis wie window.onFocus möglicherweise ein Delegat zu. Im letzten Schritt rufen Sie die initialize-Basismethode auf, um der Basisklasse der Komponente das Abschließen der Initialisierung zu ermöglichen.
ASP.NET stellt Klassen und Methoden bereit, um eine Standardereignisverwaltung für Komponenten und DOM-Elemente bereitzustellen. Verwenden Sie die Sys.EventHandlerList-Klasse zum Verwalten von Ereignissen der Komponente. Binden Sie beispielsweise Ereignisse mithilfe der Sys.EventHandlerList.addHandler-Methode, und geben Sie diese mit der Sys.EventHandlerList.removeHandler-Methode frei. Weitere Informationen hierzu finden Sie unter Sys.EventHandlerList-Klasse.
Um Ereignishandler für DOM-Elemente oder das window-Objekt zu verwalten, verwenden Sie die Sys.UI.DomEvent-Klasse. Ereignishandler können Sie beispielsweise mit der Sys.UI.DomEvent addHandler-Methode und der Sys.UI.DomEvent removeHandler-Methode binden bzw. die Bindungen wieder aufheben. Weitere Informationen hierzu finden Sie unter Sys.UI.DomEvent-Klasse.
Freigeben von Ressourcen
Wenn die benutzerdefinierte Komponente vor dem Entfernen der Komponente Ressourcen freigeben muss, überschreiben Sie die dispose-Methode, und geben Sie die Ressourcen in der überschriebenen Methode frei. Dadurch wird sichergestellt, dass die Ressourcen sofort freigegeben werden, bevor die Komponente entfernt wird. Zu den Ressourcen, die freigegeben werden sollten, können Handler für DOM-Ereignisse gehören. Indem Sie überprüfen, dass alle vorhandenen Zirkelverweise zwischen DOM-Elementen und dem Komponentenobjekt entfernt wurden, stellen Sie sicher, dass das Objekt aus dem Speicher entfernt werden kann. Weitere Informationen finden Sie unter Freigeben von Komponentenressourcen.
Verwenden einer nicht visuellen Komponente in einer Seite
Um eine benutzerdefinierte Clientkomponente in einer ASP.NET-AJAX-Anwendungsseite zu verwenden, gehen Sie folgendermaßen vor:
Registrieren Sie die Skriptbibliothek der Komponente in der Webseite.
Erstellen Sie eine Instanz der Komponente.
Die folgenden Abschnitte enthalten ausführliche Informationen zu diesen Schritten.
Registrieren der Skriptbibliothek einer Komponente in der Webseite
Skripts, die auf der Webseite für ein Clientsteuerelement erforderlich sind, können mit dem ScriptManager-Steuerelement entweder deklarativ oder programmgesteuert registriert werden. Im folgenden Beispiel wird das deklarative Markup für ein ScriptManager-Steuerelement veranschaulicht, das ein Komponentenskript registriert.
<form id="form1" >
<asp:ScriptManager ID="ScriptManager01">
<scripts>
<asp:ScriptReference path="DemoTimer.js" />
</scripts>
</asp:ScriptManager>
</form>
Das asp:ScriptManager-Element enthält ein asp:ScriptReference-Element in einem scripts-Knoten. Das path-Attribut des asp:ScriptReference-Elements verweist auf den Pfad der JS-Datei (in diesem Beispiel DemoTimer.js), in der eine Komponentenklasse definiert wird. Weitere Informationen finden Sie unter Dynamisches Zuweisen von Skriptverweisen sowie in der Übersicht über die ScriptManager-Klasse.
Als Alternative zum Registrieren von Skriptdateien mithilfe des ScriptManager-Steuerelements können Sie die Clientkomponenten mit einem benutzerdefinierten Serversteuerelement verwalten, das die IScriptControl-Schnittstelle implementiert. Das benutzerdefinierte Serversteuerelement kann die erforderlichen Komponentenskripts automatisch registrieren und deklaratives Markup zum Festlegen von Komponenteneigenschaften und Ereignisbindungen verfügbar machen. Wenn Sie Skripts mit einem benutzerdefinierten Serversteuerelement registrieren, können Sie den Seitenentwicklern die Verwendung Ihrer Komponente erleichtern. Weitere Informationen finden Sie in der Übersicht über die IScriptControl-Klasse.
Hinweis: |
---|
Alle eigenständigen Skriptdateien, die mit dem ScriptManager-Steuerelement registriert werden sollen, müssen die notifyScriptLoaded-Methode aufrufen, um die Anwendung darüber zu benachrichtigen, dass der Ladevorgang des Skripts abgeschlossen ist. Skripts, die in einer Assembly eingebettet sind, sollten diese Methode in den meisten Fällen nicht aufrufen. Weitere Informationen hierzu finden Sie unter Sys.Application.notifyScriptLoaded-Methode. |
Erstellen einer Instanz einer benutzerdefinierten Komponente
Sie instanziieren eine Clientkomponente durch Aufrufen der Sys.Component.create-Methode oder mithilfe der Verknüpfung $create. Sie übergeben Parameter an die $create-Methode, um den Komponententyp anzugeben. Sie übergeben ebenfalls ein JSON-Objekt, das einen erforderlichen ID-Wert und optionale Anfangswerte sowie optionale Ereignishandlerbindungen enthält.
Im folgenden Beispiel wird gezeigt, wie eine Komponenteninstanz durch Aufrufen der $create-Methode instanziiert wird.
var app = Sys.Application;
app.add_init(applicationInitHandler);
function applicationInitHandler(sender, args)
{
$create(Demo.Timer, {enabled:true,id:"demoTimer1", interval:2000},
{tick:OnTick}, null);
}
Weitere Informationen finden Sie unter Sys.Component.create-Methode und unter Sys.Component $create-Methode.
Erstellen der benutzerdefinierten Demo.Timer-Komponente
In diesem Abschnitt erstellen Sie eine benutzerdefinierte Clientkomponente mit dem Namen Demo.Timer, die die Component-Basisklasse erweitert. Anschließend verwenden Sie diese Komponente in einer Seite. Demo.Timer ist eine einfache Zeitgeberkomponente, die ein tick-Ereignis definiert, eine enabled-Eigenschaft und eine interval-Eigenschaft verfügbar macht und eine Änderungsbenachrichtigung für die interval-Eigenschaft auslöst. Ein Seitenentwickler, der die Demo.Timer-Komponente verwendet, kann das tick-Ereignis behandeln. Der Entwickler kann auch an das durch die geänderte Eigenschaft ausgelöste Ereignis binden und jedes Mal reagieren, wenn die interval-Eigenschaft aktualisiert wird.
So erstellen Sie den Code für die Demo.Timer-Komponente
Erstellen Sie im Stammverzeichnis einer AJAX-fähigen ASP.NET-Webanwendung eine Datei mit dem Namen DemoTimer.js.
Fügen Sie folgenden Code in die Textdatei ein:
Type.registerNamespace("Demo"); Demo.Timer = function() { Demo.Timer.initializeBase(this); this._interval = 1000; this._enabled = false; this._timer = null; } Demo.Timer.prototype = { // OK to declare value types in the prototype get_interval: function() { /// <value type="Number">Interval in milliseconds</value> return this._interval; }, set_interval: function(value) { if (this._interval !== value) { this._interval = value; this.raisePropertyChanged('interval'); if (!this.get_isUpdating() && (this._timer !== null)) { this._restartTimer(); } } }, get_enabled: function() { /// <value type="Boolean">True if timer is enabled, false if disabled.</value> return this._enabled; }, set_enabled: function(value) { if (value !== this.get_enabled()) { this._enabled = value; this.raisePropertyChanged('enabled'); if (!this.get_isUpdating()) { if (value) { this._startTimer(); } else { this._stopTimer(); } } } }, // events add_tick: function(handler) { /// <summary>Adds a event handler for the tick event.</summary> /// <param name="handler" type="Function">The handler to add to the event.</param> this.get_events().addHandler("tick", handler); }, remove_tick: function(handler) { /// <summary>Removes a event handler for the tick event.</summary> /// <param name="handler" type="Function">The handler to remove from the event.</param> this.get_events().removeHandler("tick", handler); }, dispose: function() { // call set_enabled so the property changed event fires, for potentially attached listeners. this.set_enabled(false); // make sure it stopped so we aren't called after disposal this._stopTimer(); // be sure to call base.dispose() Demo.Timer.callBaseMethod(this, 'dispose'); }, updated: function() { Demo.Timer.callBaseMethod(this, 'updated'); // called after batch updates, this.beginUpdate(), this.endUpdate(). if (this._enabled) { this._restartTimer(); } }, _timerCallback: function() { var handler = this.get_events().getHandler("tick"); if (handler) { handler(this, Sys.EventArgs.Empty); } }, _restartTimer: function() { this._stopTimer(); this._startTimer(); }, _startTimer: function() { // save timer cookie for removal later this._timer = window.setInterval(Function.createDelegate(this, this._timerCallback), this._interval); }, _stopTimer: function() { if(this._timer) { window.clearInterval(this._timer); this._timer = null; } } } Demo.Timer.registerClass('Demo.Timer', Sys.Component); // 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();
Codeerläuterung
Mit dem Code wird der Demo-Namespace durch Aufrufen der Type.registerNamespace-Methode registriert. Es wird empfohlen, alle privaten Felder im Konstruktor zu deklarieren und zu initialisieren, wie beispielsweise interval in diesem Beispiel. Vom Konstruktor wird die geerbte initializeBase-Methode aufgerufen, damit die Component Basisklassenmethoden verfügbar sind. Die initialisierte Basisklasse registriert in der Clientanwendung wiederum die Demo.Timer-Instanz als verwerfbares Objekt.
Im Prototyp werden vom Code zwei öffentliche Eigenschaften deklariert und initialisiert: interval und enabled. Zu den Eigenschaftendefinitionen gehören private Felder für ihre Werte und get- und set-Accessoren für jede Eigenschaft. In der set-Accessormethode löst der Code für jede öffentliche Eigenschaft ein propertyChanged-Ereignis aus, indem er die raisePropertyChanged-Methode aufruft. Dieses Ereignis benachrichtigt Seitenentwickler bei jeder Änderung der Eigenschaft.
Durch die add_tick-Methode und die remove_tick-Methode kann ein Seitenentwickler Methoden zum Überwachen des tick-Ereignisses hinzufügen und entfernen. Diese Methoden wiederum fügen mithilfe der Sys.EventHandlerList-Auflistung der Komponente den angegebenen Handler hinzu oder entfernen ihn. Durch die geerbte Sys.Component.events-Eigenschaft enthält das EventHandlerList-Objekt eine Auflistung der Ereignishandler der Komponente. Im Beispiels werden im Code die Sys.EventHandlerList.addHandler-Methode und die Sys.EventHandlerList.removeHandler-Methode des zurückgegebenen EventHandlerList-Objekts aufgerufen, um den angegebenen Handler hinzuzufügen oder zu entfernen.
Die Demo.Timer-Klasse überschreibt die dispose-Methode der Basisklasse, um die enabled-Eigenschaft zu aktualisieren und um Consumern anzuzeigen, dass die Komponente deaktiviert wurde. Der set-Accessor für die enabled-Eigenschaft löst das propertyChanged-Ereignis zum Senden der Benachrichtigung aus. Der Code ruft die private _stopTimer-Methode auf, um das Auslösen von tick-Ereignissen zu beenden. Im Code wird abschließend die dispose-Basismethode aufgerufen, damit die Komponente von der Anwendung freigegeben werden kann.
Verwenden der Demo.Timer-Komponente in einer Webseite
Instanzen von ASP.NET-AJAX-Clientkomponenten in einer Seite können mit einem benutzerdefinierten Serversteuerelement oder mit Clientskript in der Webseite verwaltet werden. In diesem Abschnitt erfahren Sie, wie eine Komponenteninstanz mithilfe eines Clientskripts in einer Webseite erstellt wird.
So erstellen Sie eine Seite zum Verwenden der Demo.Timer-Komponente
Erstellen Sie in dem Verzeichnis, in dem sich die Datei DemoTimer.js befindet, eine Datei namens DemoTimer.aspx, und fügen Sie folgendes Markup und folgenden Code hinzu:
<!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 > <title>Demo Timer Component</title> </head> <body> <form id="form1" > <div> <asp:ScriptManager ID="ScriptManager1" > <Scripts> <asp:ScriptReference Path="DemoTimer.js"/> </Scripts> </asp:ScriptManager> Timer Tick Count: <span id="result">0</span> </div> <script type="text/javascript"> function OnTick(sender, args) { var result = $get("result"); result.innerText = parseInt(result.innerText) + 1; } var app = Sys.Application; app.add_init(applicationInitHandler); function applicationInitHandler(sender, args) { // Create the DemoTimer component instance. // Set properties and bind events. $create(Demo.Timer, {enabled:true,id:"demoTimer1",interval:2000}, {tick:OnTick}, null, null); } </script> </form> </body> </html>
Erstellen Sie im gleichen Verzeichnis eine Datei mit dem Namen TestDemoTimer.js, und fügen Sie dieser Datei den folgenden Code hinzu:
function OnTick(sender, args) { var result = $get("result"); result.innerText = parseInt(result.innerText) + 1; } var app = Sys.Application; app.add_init(applicationInitHandler); function applicationInitHandler(sender, args) { // Create the DemoTimer component instance. // Set properties and bind events. $create(Demo.Timer, {enabled:true,id:"demoTimer1",interval:2000}, {tick:OnTick}, null, null); }
Codeerläuterung
Die Beispielseite lädt TestDemoTimer.js mithilfe von JavaScript-Code, der die beiden Funktionen OnTick und applicationInitHandler enthält. Die OnTick-Funktion behandelt das tick-Ereignis der Demo.Timer-Komponente und aktualisiert einen Indikatorwert in einem span-HTML-Element.
Die applicationInitHandler-Funktion ist ein Handler für das app_init-Ereignis. In der Funktion wird die Demo.Timer-Komponente im Clientskript durch Aufrufen der $create-Methode instanziiert, wobei die folgenden Argumente übergeben werden:
Das type-Argument ist die Demo.Timer-Klasse, die Sie zuvor erstellt haben.
Das properties-Argument besteht aus einem JSON-Objekt, das den erforderlichen ID-Wert der Komponente enthält, gefolgt von Name-Wert-Paaren, die Eigenschaftennamen mit Anfangswerten angeben. Zu Demonstrationszwecken wird die interval-Eigenschaft anfänglich auf 2000 Millisekunden festgelegt, sodass der Timer alle zwei Sekunden ein tick-Ereignis auslöst. (Für eine Produktionsanwendung würden wahrscheinliche größere Intervalle festgelegt, um den Netzwerkdatenverkehr zu reduzieren.) Die enabled-Eigenschaft der Komponente ist auf true festgelegt, sodass der Timer direkt nach seiner Instanziierung startet.
Das events-Argument enthält ein Objekt, in dem Ereignisnamen mit den zugeordneten Handlern verknüpft sind. In diesem Fall wird der onTick-Handler dem tick-Ereignis zugewiesen, das im script-Element der Seite definiert wird.
Die Datei DemoTimer.aspx ist eine ASP.NET-Webseite, die die Komponente hostet. Im ScriptManager-Steuerelement der Seite verweist das path-Attribut des asp:ScriptReference-Elements auf den Pfad der Datei DemoTimer.js, in der die Demo.Timer-Komponentenklasse definiert ist.
Siehe auch
Aufgaben
Dynamisches Zuweisen von Skriptverweisen
Konzepte
Verwenden des ASP.NET UpdatePanel-Steuerelements mit datengebundenen Steuerelementen
Arbeiten mit PageRequestManager-Ereignissen