I Web Control
Un argomento importante per tutti coloro che utilizzano Microsoft .NET 2: i web control personalizzati. In questo
articolo è una sorta di promemoria per coloro che intendono sviluppare un nuovo web control. In particolare parleremo di:
Web user control
Sicuramente quelli più semplici da creare ed utilizzare, i web user control si gestiscono un po' come una pagina
web con qualche piccola differenza.
- L'estensione del file non è .aspx ma .ascx
- Non contiene i tag html/body/head e form
- La direttiva non è @Page ma @Control
- La classe da cui derivare non è system.web.UI.Page ma system.web.UI.UserControl
Cosa altro aggiungere? Inserite i web control standard e componente il vostro nuovo control ed utilizzarlo. Questo
che vedete di seguito è un web user control inserito all'interno di questa pagina
Qualche nota
- Per accedere ai dati contenuti all'interno creare delle proprietà apposite (i membri del vostro user control sono protected
quindi non accedibili)
- I web user control hanno gli eventi gestiti in maniera naturale e trasparente (in sostanza niente codice da aggiungere)
- I web control possono essere aggiunti dinamicamente (LoadControl)
- I web control possono generare eventi propri
Ricordiamo come fare per generare un evento, utilizzando sempre il nostro web control.
Partial Class public_articles_webcontrol_custom_esempio : Inherits System.Web.UI.UserControl
ReadOnly Property saluto() As String
Get
Return Label.Text
End Get
End Property
Protected Sub Button_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button.Click
Dim name As String = Me.TextBox.Text
If name = String.Empty Then
Me.Label.Text = "Nessuno da salutare"
Else
Me.Label.Text = String.Format("Ciao {0}!", name)
End If
End Sub
End Class
A titolo di esempio immaginiamo che nel caso che il nomer inserito sia SIMONA venga generato un evento EventSimona. Per
ottenere lo scopo dobbiamo dapprima definire il nuovo evento
Public Event EventSimona()
Poi aggiungere la riga per generare l'evento
If LCase(name) = "simona" Then
RaiseEvent EventSimona()
End If
Nella pagina che utilizza il control sarà necessario registrare l'evento e fornire l'indirizzo delle funzione
che lo gestirà
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
AddHandler my.EventSimona, AddressOf GetSimona
End Sub
Private Sub GetSimona()
Me.simonatestLabel.Text = "Simona è qui!!!"
End Sub
Templated Web User Control
Per dare la massima flessibilità all'utilizzatore del nostro controllo possiamo aggiungere la possibilità
di gestione attraverso un template. Il template infatti lascia libero l'utilizzatore del nostro control per quel
che riguarda la formattazione.
A titolo di esempio vediamo come creare un control che visualizza l'ora corrente del server. Per prima cosa dobbiamo
creare un nuovo ascx file all'interno del quale dobbiamo definire solamente un PlaceHolder. All'interno del codefile invece
dobbiamo definire una proprietà del tipo ITemplate con gli attributi PersistenceMode e TemplateContainer. Infine una classa container
da creare nella directory App_Code. Vediamo i dettagli partendo dal risultato finale. L'ora che vedere è appunto generata dal nostro time control.
21.57.14
I file coinvolti sono tre
- mytime.ascx
- mytime.ascx.vb
- mytime_container.vb
Nel .ascx niente di particolare: uno stardard user control con un solo placeholder
<@ Control Language="VB" AutoEventWireup="false" CodeFile="mytime.ascx.vb" Inherits="mytime" >
Nel ascx.vb dobbiamo invece inserire una proprietà per il template e nell'evento Init la gestione del template
stesso
Partial Class mytime : Inherits System.Web.UI.UserControl
<PersistenceMode(PersistenceMode.InnerProperty)> _
<TemplateContainer(GetType(mytime_container))> _
Public Property MyTemplate() As ITemplate
Get
Return _MyTemplate
End Get
Set(ByVal value As ITemplate)
_MyTemplate = value
End Set
End Property
Private _MyTemplate As ITemplate
Public ReadOnly Property pWebTime() As String
Get
Return _pWebTime
End Get
End Property
Private _pWebTime As String = DateTime.Now.ToString("HH:mm:ss")
Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
Me.PlaceHolder.Controls.Clear()
If MyTemplate Is Nothing Then
Me.PlaceHolder.Controls.Add(New LiteralControl("Errore! Nessun template"))
Exit Sub
End If
Dim c As New mytime_container(pWebTime)
MyTemplate.InstantiateIn(c)
Me.PlaceHolder.Controls.Add(c)
End Sub
End Class
Nel .vb la gestione della classe container che espone le proprietà del controllo
Public Class mytime_container : Inherits Control : Implements INamingContainer
Sub New(ByVal currentTime As String)
_WebTime = currentTime
End Sub
ReadOnly Property WebTime() As String
Get
Return _WebTime
End Get
End Property
Private _WebTime As String
End Class
Per finire ecco come utilizzare il "Templated Web User Control" all'interno della nostra pagina
<ut:MyTime ID="Mytime2" runat="server">
<MyTemplate>
<div style="text-align:center;font-size:xx-large"><%# Container.WebTime%></div>
</MyTemplate>
</ut:MyTime>
Custom Web Control
I custom web control non posso essere costruiti in maniera interattiva come i web control. Sono infatti
basati su una nuova classe che deriva o direttamente dalla classe base WebControl oppure da un altro controllo
già esistente e parte del Framework .NET
Nella nostra classe di esempio abbiamo creato un nuovo control che aggiunge un tag fieldset al valore visualizzato.
Da notare l'ovverride del metodo Render per poter modificare quanto preparato dalla classe base.
Public Class mycustom_label : Inherits Label
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
writer.Write("<fieldset><legend>Mia Label</legend>")
MyBase.Render(writer)
writer.Write("</fieldset>")
End Sub
End Class
Ereditare dalla classe base WebControl non cambia sostanzialmente nulla, se non il fatto che non occorre
chiamare il metodo Render della classe base (Mybase.Render).
Composite control
Il composite control è una versione particolare di Custom Web Control. Infatti è un Custom Web Control che
contiene all'interno più controls che gestisce come entità unica. La classe di esempio divide in due parti il testo
che le viene impostato. Per farlo utilizza due label control affiancati. L'unica cosa particolare è l'override del
metodo CreateChildControls dove aggiungere un i controls utilizzati.
Massimo
Ecco il codice
Public Class mycomposite : Inherits CompositeControl : Implements INamingContainer
Public Property text() As String
Get
Return _text
End Get
Set(ByVal value As String)
_text = value
End Set
End Property
Private _text As String
Protected Overrides Sub CreateChildControls()
Dim tleft As New Label
Dim tright As New Label
tleft.ForeColor = Drawing.Color.Blue
tright.ForeColor = Drawing.Color.Tomato
tleft.Font.Size = FontUnit.XXLarge
tright.Font.Size = FontUnit.XXLarge
Dim l As Integer = _text.Length
If l > 1 Then
Dim h As Integer
h = Fix(_text.Length / 2)
tleft.Text = _text.Substring(0, h)
tright.Text = _text.Substring(h)
End If
Controls.Add(tleft)
Controls.Add(tright)
End Sub
End Class
Come i Web User Control anche i Custom Web Control e i Composite Custom Web Control possono diventare "Templated"
dando così un'ampia libertà al chiamante nella formattazione. Il procedimento è lo stesso dei Web User Control con una classe
container che espone le proprietà del controllo. L'unica nota riguarda la definizione della classe con l'attributo ParseChildren e
all'overrides del DataBind.
<ParseChildren(true)> _
Public Class mycomposite : Inherits CompositeControl : Implements INamingContainer
.....
public Overrides Sub DataBind()
EnsureChildControl()
MyBase.DataBind()
end sub
....
end class
Supporto Design Time
Una caratteristica importante dei Custom Web Controls (composite controls inclusi) è di poter essere compilati
com .DLL per una più facile distribuzione. Altre caratteristiche importanti sono quelle relative al supporto che
si può aggiungere al control per facilitare l'inserimento del control nei nostri form. In altre parole stiamo parlando
di tutte quelle caratteristiche che verranno utilizzate durante il Design Time.
Una volta compilato, il nostro Custom Web Control può essere infatti aggiunto alla toolbar degli strumenti. Come
prima cosa è possibile aggiungere una bitmap che verrà visualizzata solo nella casella degli strumenti. Nel codice
mostrato di seguito si mostra come aggiungere una bitmap che è embedded nella dll stessa.
<ToolboxBitmap(GetType(MyControl),"MyLib.MyControl.bmp") > _
public class MyControl : inherits WebControl
...
end class
Un'altra caratteristica interessante è quella di fornire il rendering del nostro control a design time. Per questo
scopo è necessario creare una classe apposita che deriva da ControlDesigner. Questa classe deve effettuare l'override
del metodo GetDesignTimeHtml per fornire la visualizzazione voluta.
imports System.ComponentModel
public class MyControlDesigner : inherits System.Web.UI.Design.ControlDesigner
public overrides function GetDesignTimeHtml() as string
....
return "Any HTML here!"
end function
end class
Una volta creata la classe design time bisogna legarla alla classe control attraverso l'attributo Designer
<ToolboxBitmap(GetType(MyControl),"MyLib.MyControl.bmp") > _
<Designer("MyLib.MyControlDesigner","MyLib") > _
public class MyControl : inherits WebControl
...
end class