Creazione di eventi client personalizzati
Aggiornamento: novembre 2007
La funzionalità AJAX in ASP.NET include un modello di eventi client a più livelli completo. La classe Sys.Application fornisce eventi a livello di applicazione. La classe Sys.WebForms.PageRequestManager fornisce eventi relativi alle parti della pagina coinvolte nel rendering a pagina parziale. I singoli componenti, ad esempio controlli e comportamenti, dispongono di eventi propri. Per ulteriori informazioni su questi eventi, vedere Eventi del ciclo di vita del client AJAX.
ASP.NET consente anche di aggiungere eventi al ciclo di vita lato client. La classe Sys.UI.DomEvent consente di associare eventi DOM (Document Object Model) HTML ai componenti ASP.NET AJAX personalizzati. In aggiunta, la classe Sys.EventHandlerList consente di creare direttamente nuovi eventi client ASP.NET AJAX.
Associazione a eventi DOM
In molti casi, un evento con il quale si desidera lavorare corrisponde a un evento definito nel DOM HTML. Ad esempio, un pulsante ASP.NET AJAX personalizzato può utilizzare l'evento click dell'elemento <button> HTML al quale è associato. Per associare un evento basato su DOM a un'applicazione ASP.NET AJAX o a un componente personalizzato, utilizzare il metodo addHandler della classe DomEvent, come illustrato nell'esempio che segue:
Sys.UI.DomEvent.addHandler(element, 'click', this.myClickHandler);
È anche possibile utilizzare il collegamento $ addHandler, come mostrato nell'esempio che segue:
$addHandler(element, 'click', this.myClickHandler);
Il metodo addHandler accetta tre parametri: element, eventName e handler. Il parametro element è un riferimento all'elemento DOM che espone l'evento. Il parametro eventName è il nome dell'evento DOM. Il parametro handler è un riferimento alla funzione da chiamare quando viene generato l'evento. Per ulteriori informazioni, vedere Metodo addHandler di Sys.UI.DomEvent.
Per rimuovere un gestore per un evento DOM, chiamare il metodo Sys.UI.DomEvent.removeHandler o il collegamento $ removeHandler, passando gli stessi parametri che vengono passati a addHandler.
![]() |
---|
I nomi di evento passati alle funzioni addHandler e removeHandler non devono includere il prefisso "on". Ad esempio, utilizzare "click" anziché "onclick". |
Aggiunta e rimozione di gestori eventi personalizzati
Per aggiungere un nuovo gestore eventi per un evento di un componente ASP.NET AJAX personalizzato, utilizzare il metodo addHandler della classe Sys.EventHandlerList. Tutti gli eventi client e i gestori eventi associati nel modello di eventi ASP.NET AJAX sono archiviati in un oggetto EventHandlerList, il quale rappresenta un dizionario specializzato per tale scopo. Ogni componente, incluso l'oggetto Application corrente, possiede un'istanza EventHandlerList propria. Aggiungendo un elemento all'oggetto EventHandlerList, viene aggiunto un evento e un gestore eventi nuovo al componente associato. Aggiungere gli eventi utilizzando la sintassi seguente:
this.get_events().addHandler(event, handler);
La proprietà events della classe Sys.Component restituisce l'istanza EventHandlerList per tale componente. La proprietà events viene ereditata dalle classi Sys.UI.Control, Sys.UI.Behavior e Sys.Application. Il parametro event è il nome dell'evento nuovo o esistente per il quale aggiungere un gestore. Il parametro handler è un riferimento alla funzione da chiamare quando viene generato l'evento. Impostando il parametro event su un nuovo valore, viene aggiunto un nuovo evento al dizionario.
Per rimuovere un evento personalizzato dal dizionario, utilizzare il metodo removeHandler della classe Sys.EventHandlerList, che accetta gli stessi parametri di addHandler.
Per aggiungere gestori a eventi già definiti in Microsoft AJAX Library, utilizzare la funzione di accesso add_ per un dato evento, come illustrato nell'esempio che segue:
Sys.Application.add_load(myLoadHandler);
Generazione di eventi personalizzati
Per generare un evento personalizzato, chiamare il metodo getHandler dell'istanza EventHandlerList, passando il nome dell'evento come parametro. Questo metodo restituisce una funzione che aggrega tutte le funzioni che rappresentano un gestore per tale evento. Chiamare la funzione restituita per generare l'evento, come illustrato nell'esempio che segue:
var h = this.get_events().getHandler('myCustomEvent')
if (h) h(this, Sys.EventArgs.Empty);
Per convenzione, i gestori eventi accettano due parametri: sender e eventArgs. Il mittente è il componente al quale viene applicato l'evento, in genere this. Il parametro eventArgs fa riferimento a un oggetto Sys.EventArgs. Questo oggetto può contenere informazioni passate all'evento, ad esempio le coordinate del mouse. Se la firma della funzione restituita da getHandler corrisponde a quella di tutte le funzioni del gestore associato, è possibile omettere i parametri sender e eventArgs. Tuttavia è consigliabile includere i parametri, come nell'esempio illustrato in precedenza.
Esempio
Descrizione
Nell'esempio seguente viene creato un semplice test a risposta multipla con due sezioni. Una volta risposto a tutte le domande di una sezione, il colore di sfondo di tale sezione cambia. Quando l'utente fa clic sul pulsante alla fine del test, un messaggio di stato accanto a ogni domanda visualizza se la risposta è corretta.
L'applicazione include istanze di due controlli personalizzati. Il controllo Question viene associato a un elemento <select> HTML, mentre il controllo Section viene associato a un elemento <div> contenente uno o più controlli Question. Il controllo Question espone un evento select, associato all'evento onChange dell'elemento <select> sottostante da un'istanza Sys.UI.DomEvent. Il controllo Section espone un evento complete, generato da una funzione definita dall'utente una volta risposto a tutti i controlli Question nell'istanza Section.
Codice
Nell'esempio seguente viene illustrata la pagina Default.aspx che crea le istanze del componente e gestisce gli eventi.
<%@ 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>
Nell'esempio riportato di seguito viene illustrato il file Question.js che definisce il controllo 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();
Nell'esempio riportato di seguito viene illustrato il file Section.js che definisce il controllo 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();
Vedere anche
Attività
Creazione di controlli client AJAX personalizzati