FindControl & INamingConteiner

di Marco Leoncini, in asp.net,

è passato molto dal mio ultimo post, il motivo principale è perche ho poco da dire, e come amo ricordare: meglio stare zitti e dare l'impressione di essere "idioti" che aprire bocca e darne la conferma, non so quante volte lo detto a mia suocera ?

Riprendo con una "sotto" categoria di asp.net, ovvero: asp.net, siamo fatti così, in onore dell'omonimo cartone, dove lo spettatore era invitato a fare un giro per il corpo umano in compagnia di due globuli rossi e un attraente globulessa :D.

Vi siete mai chiesti perche, ad esempio nell'event handler dell'evento RowDataBound di un GridView, le seguenti righe di codice producono il solito risulatato?

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) 
{ 
if (e.Row.RowType == DataControlRowType.DataRow) 
{ 
Control _control = e.Row.FindControl("nome"); 
Control _controlBis = e.Row.Cells[0].FindControl("nome"); 
} 
} 

Il controllo con ID "nome" si trova nella cella che a sua volta è contenuta nella riga, eppure sappiamo che il metodo FindControl non esegue ricerche ricorsive, come vedremo questa affermazione è vera in parte o parzialmente falsa, dipende dai punti di vista.

Tutto inizia nella classe Control, in pratica la mamma di tutti i controlli, poche righe nel costruttore per controllare l'implementazione dell'interfaccia INamingContainer , il risultato viene memorizzato in una struttura interna .

public Control() 
{ 
if (this is INamingContainer) 
{ 
this.flags.Set(0x80); 
} 
} 

FindControl , o meglio il suo overload protected si assicura che i controlli figlio siano stati creati, recupera se possibile il NamingContainer per invocare su di esso il metodo FindControl altrimenti ritorna null.

if (!this.flags[0x80]) 
{ 
Control namingContainer = this.NamingContainer; 
if (namingContainer != null) 
{ 
return namingContainer.FindControl(id, pathOffset); 
} 
return null; 
} 

Tralasciando un po' di codice, sostanzialmente qualche if, il prossimo passo è l'esecuzione del metodo :

private void EnsureNamedControlsTable() 
{ 
this._occasionalFields.NamedControls = new HybridDictionary(this._occasionalFields.NamedControlsID, true); 
this.FillNamedControlsTable(this, this._occasionalFields.Controls); 
} 
Inizilizzato il contenitore lo riempiamo con i controlli eseguendo il metodo FillNamedControlsTable 
private void FillNamedControlsTable(Control namingContainer, ControlCollection controls) 
{ 
int count = controls.Count; 
for (int i = 0; i < count; i++) 
{ 
Control control = controls[i]; 
if (control._id != null) 
{ 
try 
{ 
namingContainer.EnsureOccasionalFields(); 
namingContainer._occasionalFields.NamedControls.Add(control._id, control); 
} 
catch 
{ 
throw new HttpException(SR.GetString("Duplicate_id_used", new object[] { control._id, "FindControl" })); 
} 
} 
if (control.HasControls() && !control.flags[0x80]) 
{ 
this.FillNamedControlsTable(namingContainer, control.Controls); 
} 
} 
} 

Ogni controllo viene aggiunto alla collezione ricorsivamente fino a quando non viene trovato un altro controllo che implementa l'interfaccia INamingContainer, in modo non proprio corretto possiamo affermare che FindControl è un metodo ricorsivo controllato dall'interfaccia INamingContainer.

Le ultime righe di codice sono dedicate a recuperare dalla collezione NamedControls il controllo richiesto.

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.

Nella stessa categoria
I più letti del mese