Oltre ai Web User Control il Framework .NET mette a disposizione un altro metodo per creare nuovi controlli Web: la definizione di una Web Control Library.
La differenza principale tra i due tipi di controlli riguarda la fase di progettazione e consiste nella semplicità di creazione da una parte e nella facilità d'uso dall'altra. I controlli Web sono semplici da creare, dal momento che si realizzano in maniera visuale, dispongono del code behind e supportano la gestione degli eventi.
Tuttavia, un Web User Control non può essere aggiunto alla Casella degli strumenti ed è rappresentato in maniera statica quando viene aggiunto ad un pagina (ovvero la modifica di una sua proprietà non si riflette nelle visualizzazione all'interno del Designer, ma è visibile solo in fase di esecuzione).
Inoltre, l'unico modo di condividere il controllo tra applicazioni diverse consiste nell'inserirne una copia distinta in ciascun progetto, soluzione che richiede una maggiore gestione nel caso in cui si apportino modifiche al controllo.
Una Web Control Library invece in genere si realizza scrivendo a mano il codice che poi sarà compilato. Dunque è più difficile da realizzare. Una volta realizzato il controllo, tuttavia, è possibile aggiungerlo alla Casella degli strumenti e gestirlo in modo analogo a quanto visto per i controlli standard.
Proviamo a creare una Web Control Library, cercando di analizzare le caratteristiche principali di questo tipo di controlli.
Dopo aver creato un sito ASP .NET, aggiungiamo un progetto alla soluzione e selezioniamo come tipo di progetto "Web Control Library", come evidenziato in figura.
L'editor di Visual Studio aprirà automaticamente il file "WebCustomControl1.cs". Analizziamo il codice inserito di default nel file (alcune parti sono state omesse per motivi di spazio):
using System;
//Altra clausole using...
namespace WebControlLibrary1
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:WebCustomControl1 runat=server>
</{0}:WebCustomControl1>")]
public class WebCustomControl1 : WebControl
{
private string text;
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
public string Text
{
//Get e set della variabile "text".
}
protected override void Render(HtmlTextWriter output)
{
output.Write(Text);
}
}
}
Ogni controllo estende la classe WebControl, che fornisce proprietà, metodi ed eventi comuni a tutti i controlli server Web.
Alla dichiarazione della classe ed alla proprietà "Text" sono stati aggiunti, tra parentesi quadre, i cosiddetti
Custom Attributes, ovvero una serie di attributi che forniscono informazioni aggiuntive sulle classi, sui metodi e sulle proprietà.
Ad esempio, ToolboxData indica quale tag è associato al controllo: in pratica, quando tale controllo sarà inserito in una pagina, esso sarà identificato dal tag specificato in questo attributo. Ancora, Category specifica la categoria in cui sarà visualizzata la proprietà Text all'interno della visualizzazione per categorie della finestra Properties.
Un'analisi dettagliata dei Custom Attributes esula dagli obiettivi di questo corso, per cui si rimanda alla guida in linea.
Concentriamoci invece sul metodo Render(), il "cuore" del Web Control: esso, infatti, specifica qual è il codice HTML che deve essere inserito nella pagina per visualizzare il controllo. Questa routine riceve come argomento un oggetto di tipo
HtmlTextWriter su cui scrivere il codice HTML.
Senza scendere nei dettagli, il metodo Render() viene automaticamente richiamato dal runtime del Framework sia quando il controllo è visualizzato in una pagina ASP .NET nel Visual Web Developer, sia quando deve essere generato il contenuto HTML da inviare al browser.
Nel primo caso, output rappresenta la pagina all'interno dell'editor, nel secondo si riferisce alla pagina che viene inviata al client per la visualizzazione nel browser (in pratica, il codice HTML che viene scritto dal metodo Render() è il codice che l'utente riceve quando richiede la pagina al server).
Anche i controlli Web standard si comportano nello stesso modo: ogni controllo inserito in una pagina genera il codice HTML
necessario alla sua visualizzazione tramite il metodo Render().
Ad esempio, la routine Render() di un controllo Label produce il seguente codice HTML:
<span id="Label1">Label</span>
Tornando al nostro Web Custom Control, la sua routine Render() si limita a scrivere nella pagina il contenuto della variabile text, senza aggiungere alcuna formattazione HTML. Proviamo ad inserire questo controllo in una Web Form.
Anzitutto dobbiamo compilare il file DLL che sarà utilizzato dall'applicazione ASP .NET. Dopo esserci assicurati che il progetto selezionato nel Solution Explorer sia "WebControlLibrary1", clicchiamo su comando Build>Build ebControlLibrary1.
Ora apriamo il file "Default.aspx" in visualizzazione design. La Toolbox si è arricchita di una nuova scheda che corrisponde alla nostra Web Control Library: essa contiene una voce per ogni classe che estende WebControl contenuta al suo interno: ognuna di esse, infatti, rappresenta un oggetto che può essere inserito nella pagina. Per il momento c'è solo WebCustomControl1.
Aggiungiamo il nostro contollo alla pagina e, nella finestra delle proprietà, modifichiamo il valore di Text: a differenza di quanto avviene con i Web User Control, la modifica si riflette anche in fase di progettazione. Eseguiamo l'applicazione e verifichiamo il risultato nel browser.
Ora modifichiamo il controllo perchè il testo specificato appaia automaticamente in grassetto. Ricordando quanto detto in precedenza, è sufficiente modificare il codice HTML generato dal controllo, ovvero intervenire sul suo metodo Render().
Poichè il metodo Write() dell'oggetto HtmlTextWriter si limita a scrivere sulla pagina tutto quello che riceve come argomento, un primo modo per fare quello che vogliamo potrebbe essere inserire tutto in un'unica istruzione:
output.Write("<b>" + Text + "</b>");
Questa soluzione è corretta, ma rischia di creare confusione, inoltre la possibilità di dimenticare qualche carattere <, > oppure / cresce all'aumentare del numero di tag da inserire.
Possiamo invece usare altri metodi messi a disposizione da HtmlTextWriter per produrre codice più leggibile e con una distinzione maggiore tra tag HTML e contenuto vero e proprio:
protected override void Render(HtmlTextWriter output)
{
output.WriteBeginTag("b");
output.Write(HtmlTextWriter.TagRightChar);
output.Write(Text);
output.WriteEndTag("b");
}
Il metodo WriteBeginTag() scrive il carattere < e il tag indicato come argomento, ma non lo chiude con > perchè, in generale, esso potrebbe contenere degli attributi (da specificare con il metodo WriteAttribute()). Per questo motivo è necessaria la successiva istruzione di Write(), che scrive semplicemente il carattere > (HtmlTextWriter.TagRightChar()).
In alternativa a queste due istruzioni, avremmo potuto usare semplicemente:
output.WriteFullBeginTag("b"); //Scrive <b>
Dopo aver stampato il testo vero e proprio, chiudiamo il tag con il metodo WriteEndTag(). Ora ricompiliamo il controllo e visualizziamo il file "Default.aspx". Per osservare il nuovo comportamento dell'oggetto all'interno del Designer potrebbe essere necessario chiudere e riaprire la pagina.
Visualizzando il sorgente HTML della pagina nel browser, notiamo che il testo specificato nella proprietà Text del controllo è stato inserito tra i tag <b> e </b>.
È possibile scaricare tutto il codice che abbiamo realizzato cliccando .
Anche questi controlli, come i controlli Web utente, una volta inseriti in una pagina prevedono l'uso della clausola @ Register associata.