Crad's .NET Blog

L'UGIblog di Marco De Sanctis
posts - 190, comments - 457, trackbacks - 70

Come far sapere ad un Component chi lo ospita?

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

Print | posted on lunedì 10 aprile 2006 02:54 | Filed Under [ .Net 2.0 Visual Studio Windows Forms ]

Powered by:
Powered By Subtext Powered By ASP.NET