Il titolo non sarà la massima espressione di linguaggio
tecnico, però è un problema che mi sono trovato ad affrontare nel weekend
sviluppando le mie
Actions
Ora, chi le ha scaricate e magari ha avuto modo di guardarne i sorgenti, sa
che si tratta di oggetti che ereditano da Component e che vanno sistemati su una
Windows Form. Mi sono trovato nella necessità di avere, nella mia ActionList, un
riferimento alla Form su cui essa giace. Requisito fondamentale: tutto deve
essere "trasparente" all'utente, senza cioé richiedere che qualcuno si metta lì
ad impostare chissà che proprietà.
Mi è subito sembrato un problema non proprio banale, meno male che ad un
certo punto ho avuto l'illuminazione: "Caspita, ho usato mille volte ErrorProvider che visualizza icone su
una Form. Dovrà pur avere un riferimento! Vediamo un po' come
fa!".
Reflector alla
mano, ho scoperto che in realtà il procedimento non è dei più complessi: basta
effettuare l'override della proprietà Site che, tra le varie cose, permette di risalire al
ContainerControl
del componente. Come? Così:
private ContainerControl containerControl;
public ContainerControl ContainerControl
{
get { return containerControl; }
set { containerControl = value; }
}
public override ISite Site
{
get
{
return base.Site;
}
set
{
base.Site = value;
// Questo è il codice che "does the trick!"
if (value != null)
{
IDesignerHost host1 = value.GetService(typeof(IDesignerHost)) as IDesignerHost;
if (host1 != null)
{
IComponent component1 = host1.RootComponent;
if (component1 is ContainerControl)
{
this.ContainerControl = (ContainerControl)component1;
}
}
}
}
}
Ora non mi dilungherò molto sulla funzione della
proprietà Site, dico solo che è utilizzata da Visual Studio a design time, ad
esempio, per dotare ogni controllo di quella proprietà (Name), scritta tra parentesi. Ciò che facciamo è,
quando il designer ne setta il valore, risalire al RootComponent che lo hosta e
settare opportunamente la proprietà ContainerControl. Quest'ultima è una
proprietà public e, come tale, viene serializzata dal generatore di codice di
Visual Studio. Risultato? Nella InitializeComponent della Form su cui
abbiamo messo il nostro componente, troviamo una bellissima riga di codice
simile alla seguente:
this.myComponent.ContainerControl = this;
Piccola considerazione: quando sviluppo custom
controls/components, incontro spesso problemi che rischiano di farmi perdere
parecchio tempo su Google alla ricerca di una soluzione. Bene, spesso la
soluzione è già lì, nel mio hard disk, nascosta da qualche parte tra le n-mila
classi del Framework. Morale: credo che Reflector sia
un tool indispensabile per ogni sviluppatore e permetta di imparare (e capire)
veramente tanto.
powered by IMHO 1.3