Realizzare un controllo custom in ASP.NET AJAX - Seconda parte

di Efran Cobisi, in ASP.NET 2.0,

L'articolo si compone di due parti. Nella prima parte sono stati descritti i concetti generali relativi al client framework di ASP.NET AJAX sfruttati nella creazione dei controlli AJAX-enabled. Inoltre è stato introdotto un esempio pratico che riguarda la realizzazione di un controllo con vista a tab verticali. Nella seconda parte dell'articolo viene completato lo studio dettagliato del controllo introdotto nella prima parte, con commenti e spiegazioni in ogni passaggio di interesse. L'esempio viene proposto anche in allegato all'articolo.

Inizializzazione del controllo e dei gestori di evento

All'atto della sovrapposizione del puntatore su di un'etichetta, è conveniente, tralasciando il problema del timeout da 200 millisecondi, nascondere tutti i pannelli di contenuto dei tab esistenti e lasciare visibile solo quello di interesse.

Effettuare una particolare operazione su tutti i tab del controllo ne implica il recupero e l'iterazione: al fine di velocizzare queste attività, è consigliabile effettuare un censimento dei tab disponibili all'atto dell'inizializzazione del controllo, in maniera tale da memorizzarne la collezione risultante in memoria: così facendo, anzichè scomodare l'engine del browser per effettuare un lookup all'interno dell'albero DOM, i gestori di evento possono utilizzare la collezione sopra menzionata ed il tempo necessario all'esecuzione verrà in gran parte ridotto.

Una volta messo a disposizione un array membro di istanza per tale collezione, è sufficiente iterare utilizzando la funzione _getTab(), fino a quando questa ritorna un valore nullo, indice del fatto che l'iterazione può avere termine.

// Popola l'array di tab utilizzato internamente

var tabIndex = 0;
var ctrlTab = this._getTab(tabIndex);

while (ctrlTab !== null)
{
  // Aggiunge il tab alla collezione

  this._tabs.push(ctrlTab);

  // Imposta la modalità di visualizzazione del controllo

  ctrlTab.Content.set_visibilityMode(Sys.UI.VisibilityMode.collapse);

  // Prosegue con il ciclo

  tabIndex++;
  ctrlTab = this._getTab(tabIndex);
}

È conveniente effettuare l'associazione dei gestori di evento per ciascuna etichetta all'interno del ciclo appena esposto, sfruttando il fatto che è possibile accedere alle componenti DOM del tab tramite la variabile locale ctrlTab.

Prevedendo due eventi per ciascuna etichetta, mouseover e mouseout, è sufficiente sfruttare la funzione scorciatoria $addHandlers() e collegare tali eventi ai due gestori che ancora devono essere implementati.

// Aggiunge i gestori di evento al tab corrente

$addHandlers(ctrlTab.Label.get_element(),
  {
    mouseover: this._onLabelMouseOver,
    mouseout: this._onLabelMouseOut
  },
  this);

Come diretta conseguenza è consigliabile includere il codice di cleanup dei gestori di evento all'interno del corpo del metodo dispose(), così come anticipato. Risulta efficace in questo contesto fare uso della funzione scorciatoia $clearHandlers(), che rimuove tutti i gestori di evento (precedentemente definiti tramite i metodi addHandler() o addHandlers() di Sys.UI.DomElement, scorciatoie incluse) per un particolare elemento:

dispose : function()
{
  // Rimuove i gestori di evento per tutti i tab

  for (tabIndex in this._tabs)
    $clearHandlers(this._tabs[tabIndex].Label.get_element());

  Cobisi.TabViewContainer.callBaseMethod(this, 'dispose');
}

Tornando al gestore dell'evento di sovrapposizione del puntatore, è sufficiente ora predisporne il corpo affinchè venga sfruttata la collezione di tab, per nascondere in primo luogo ciascun elemento e, successivamente, visualizzare solo quello di interesse. Per recuperare l'elemento DOM da cui è stato scatenato l'evento è necessario utilizzare il parametro fornito automaticamente da ASP.NET AJAX al metodo predisposto. Tale oggetto della classe Sys.UI.DomEvent incapsula in modalità cross browser l'accesso a tutte le informazioni pertinenti all'evento in fase di gestione: in particolare il valore del campo target permette di accedere all'elemento DOM cercato.

Visualizzare il pannello del contenuto del tab attivo richiede dunque una semplice iterazione accompagnata dalla chiamata al metodo set_visible(), membro di Sys.UI.Control, che permette di operare sulla visibilità del controllo manipolando dietro alle quinte gli stili di quest'ultimo. L'iterazione di un array può essere effettuata utilizzando la comoda funzione forEach() della classe Array: come si può evincere dal listato che segue, tale metodo è molto simile all'omonimo ForEach() del tipo generic List (List(Of T) per chi sviluppa in Visual Basic).

// Recupera il tab da visualizzare

var tabToShow = null;

Array.forEach(this._tabs, function(item)
{
  if (eventInfo.target == item.Label.get_element())
    tabToShow = item;
}, this);

tabToShow.Content.set_visible(true);

Come si può dedurre dal listato precedente, ASP.NET AJAX consente di utilizzare in maniera estremamente naturale la keyword this del linguaggio JavaScript, accedendo ai membri di ciascuna istanza: si noti a tal proposito l'impiego del membro _tabs. Nonostante questo dettaglio possa sembrare superfluo, esso permette di superare in realtà una serie di problemi legati ad una precedente inconsistenza dell'impiego di tale keyword: essa può infatti riferirsi sia ad una istanza di classe definita dall'utente, sia, come nel caso dei gestori di evento, all'elemento DOM scatenante. Questa inconsistenza è fortunatamente superata grazie ad ASP.NET AJAX, che si fa carico di applicare alla keyword this un riferimento consistente all'istanza di classe, anche nel caso dei gestori di evento.

Un ostacolo di non semplice soluzione è invece rappresentato da tutte quelle funzioni che operano nel contesto dell'oggetto intrinseco window. In tal caso (come in altri, non analizzati in questo articolo), lo scope della keyword this, se utilizzata in tali funzioni, corrisponde allo stesso oggetto window. Per risolvere questo problema è possibile utilizzare alcuni metodi della classe Function: createDelegate(instance, method) permette infatti di definire un delegato, ovvero una funzione, il cui unico scopo è richiamare il metodo specificato, attribuendo preventivamente alla keyword this il riferimento all'istanza desiderata.

4 pagine in totale: 1 2 3 4

Attenzione: Questo articolo contiene un allegato.

Contenuti dell'articolo

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti