Databinding e templating con ASP.NET

2 pagine in totale: <<Indietro 1 [2]

Il templating

I templates sono pezzi di codice HTML/ASP.NET o meglio, codice che crea controlli che possiamo riutilizzare quando vogliamo, anche più di una volta. Il loro maggior impiego è nei controlli che caricano sorgente dati, come Repeater, DataList, DataGrid, ma vengono utili anche qualora si voglia generare dell'HTML piuttosto che un altro.

I templates non sono altro che classi che implementano ITemplate , interfaccia dispone di un solo membro, InstantiateIn(Control) .

Il concetto alla base del templating è semplice: chi vuole utilizzare il template, istanzia la classe e chiama il metodo InstantiateIn passando il controllo contenitore.

Se volessimo fare un template che mostra una Label con l'ora corrente, dovremo scrivere:

public class DateTimeTemplate : ITemplate
{
  void ITemplate.InstantiateIn(Control c)
  {
   Label date = new Label();
   date.Text = DateTime.Now.ToString();
   c.Controls.Add(date);
  }
}

La sua massima utilità però deriva dall'integrazione con il parser, perchè se un controllo è marcato con l'attributo ParseChildren(true) , ogni tag figlio verrà parserizzato come proprietà.

Considerando ancora l'oggetto Repeater, il tag di tipo ITemplate è una proprietà della classe. Il parser però riconoscerà il tipo e creerà un template sul metodo che crea i controlli figli del tag. Rivediamo il Repeater precedente:

<asp:Repeater runat="server">
  <ItemTemplate>
      <%#DataBinder.Eval(Container.DataItem, "campo")%>
  </ItemTemplate>
</asp:Repeater>

Il codice prodotto sarà:

// Costruisco il repeter
private System.Web.UI.Control __BuildControl__control3() {
  // Istanzio la classe
  this.__control3 = new System.Web.UI.WebControls.Repeater();
 
  // Imposto la proprietà creando un template
  // che mappa su __BuildControl__control4
  this.__control3.ItemTemplate = new System.Web.UI.CompiledTemplateBuilder(new System.Web.UI.BuildTemplateMethod(this.__BuildControl__control4));

  return this.__control3;
}

private void __BuildControl__control4(System.Web.UI.Control __ctrl)
{
  // Creo i controlli del template
  this.__BuildControl__control5();

  // Aggiungo i controlli del template al contenitore passato
  System.Web.UI.IParserAccessor __parser = ((System.Web.UI.IParserAccessor)(__ctrl));
  __parser.AddParsedSubObject(this.__control5);
}


private System.Web.UI.Control __BuildControl__control5()
{
  this.__control5 = new System.Web.UI.DataBoundLiteralControl(1, 1);
  // Intercetto il binding
  this.__control5.DataBinding += new System.EventHandler(this.__DataBind__control5);
  return this.__control5;
}

public void __DataBind__control5(object sender, System.EventArgs e) {
  System.Web.UI.WebControls.RepeaterItem Container = ((System.Web.UI.WebControls.RepeaterItem)(target.BindingContainer));;
  System.Web.UI.DataBoundLiteralControl target = ((System.Web.UI.DataBoundLiteralControl)(sender));

  target.SetDataBoundString(0, System.Convert.ToString(DataBinder.Eval(Container.DataItem, "campo")));
}

Analizzando il codice, possiamo notare che viene creato il Repeater e assegnato alla proprietà ItemTemplate un CompiledTemplateBuilder .

Si tratta di una classe standard che implementa ITemplate e che bypassa la chiamata IstantiateIn al metodo __BuildControl__control4 tramite delegate. Una volta creato il template potremo chiamare quante volte vogliamo questo metodo, perchè sarà infatti compito del Repeater, tramite ItemTemplate, richiamarlo quante volte sono il numero dei records della sorgente.

Un'ultima nota va alla procedura che viene scatenata in fase di binding (__DataBind__control5). Come fa il parser a sapere che target.BindingContainer sarà un RepeaterItem? Lo si istruisce marcando la proprietà con l'attributo TemplateContainer che specifica il tipo del contenitore.

Se sviluppate un componente custom dovete tener conto che un template può contenere controlli con un ID e che questo potrà essere creato più volte. Se il contenitore (tipo che implementa INamingContainer) è unico per tutti, verrà sollevata un'eccezione poiché l'ID non è univo.

Il Repeater risolve questo problema utilizzando come Container un RepeaterItem per ogni IstantiateIn, classe che eredita da Control e che implementa INamingContainer.

Conclusioni

Questa profonda analisi è molto importante per capire ciò che facciamo quando scriviamo codice per ASP.NET e credo ci renda molto più rapidi nel capire e risolvere problemi che si presentano con pagine e controlli complessi.

Nel prossimo articolo vedremo un esempio pratico, come creare un controllo che sfrutti templating e databind estendendo le funzionalità del Repeater.

Approfondimenti

2 pagine in totale: <<Indietro 1 [2]

Contenuti dell'articolo

Commenti
Dai un voto a questo articolo, ci aiuterà a migliorare il nostro sito (1 è il voto minimo, 5 il massimo).

Per procedere al rating dell'articolo devi essere autenticato.

Aggiungi un nuovo commento »»»
Per inserire un commento, devi registrarti alla nostra community.


TUTORIALS
TOP TEN ARTICOLI
NOTIFICHE

Iscriviti alla nostra newsletter nuoviarticoli per ricevere e-mail le notifiche!

Indirizzo e-mail:
PROVIDER ASP.NET 2.0

Seleziona il database per avere il web.config pronto per Membership, Roles e Profile API.



IN EVIDENZA
MISC