Design-Time integration support

Nel corso dello sviluppo delle nostre applicazioni in Visual Studio la prima cosa che abbiamo dovuto imparare è stata sicuramente la classica applicazione "Hello word" e da li ci siamo addentrati nel framework .net alla scoperta del vasto mondo dei namespace e delle classi presenti. Ci siamo preoccupati del debug in fase di esecuzione e di implementare le funzionalità più consone alle nostre aspettative. Tutto questo nel mondo delle Windows Forms Applications ha un nome ben preciso: Run-Time, ossia tutto ciò che viene eseguito dal momento in cui facciamo partire la nostra applicazione.

Ciò che accade durante l'interazione con i controlli e i componenti (sulla differenza di queste due classi vi rimando ad un prossimo articolo) prende il nome di Design-Time. La fase di realizzazione di una interfaccia tramite l'aggiunta di controlli su Form, UserControl o Components e l'interazione con la finestra delle proprietà assume il nome di Design-Time.

Con il nome Windows Forms Designer si deve intendere l'ambiente di sviluppo offertoci da VS in fase di disegno (spostamento dei controlli sui container (forms, panel, usercontrol)), impostazione delle proprietà. Trascinando, ad esmpio, un Button su una Forms, il Windows Forms Designer va ad interagine con la classe Button (qui siamo in fase di design-time, e volendo potremmo anche fare il debug per vedere cosa succede dietro le quinte...) andando a leggere gli attributi presenti sulla dichiarazione della classe ed a verificare le interfacce che questi implementano. A questo punto bisogna fare una doverosa osservazione:

Per poter utilizzare le funzionalità offerte dal design-time, ogni Component, Control o UserControl deve implemnentare l'interfaccia IComponent.

Intrface IComponent: IDisposable {
ISite Site {get; set;}
event EventHandler Disposed;
}

Dall'immagine che segue si capsice che i comuni controlli presenti sulla toolbox di windows o un Controllo utente da noi creato implementano già questa interfaccia.


Se volessimo realizzare un componente partento da zero potremmo implementare l'interfaccia IComponent (dal namespace System.ComponentModel) e scrivere il codice per i metodi e le proprietà implementate. La cosa più semplice è probabilmente quella di ereditare da Component che già implementa in modo implicito l'interfaccia IComponent o usare una delle classi presenti nel namespace System.Windows.Forms che ereditano in modo diretto o indiretto da Component (parte destra dell'immagine). In quest'ultimo caso il nostro controllo avrà tutte le proprietà ed i metodi solitamente presenti nei controlli di base di VS, quali ad esempio BackColor, ForeColor, Text etc..


Il Windows Forms Designer implementa l'interfaccia IDesignerHost (nota come Designer host), che permette di gestire gli oggetti nel design-time fornendo i serivizi necessari.



namespace System.ComponentModel.Design {

public interface IDesignerHost : IServiceContainer, IServiceProvider{

IContainer Container { get; }

.........}}


IDesignerHost memorizza i riferimenti delle interfacce IComponent, perciò nel momento in cui trasciniamo controlli su una Form, il designer host aggiunge un riferimento a questo controllo, ed alla Form stessa, che implementano l'interfaccia IComponent. E' possibile accedere alla collezione tramite la proprietà Container che espone la proprità Components di tipo ComponentCollection.

namespace System.ComponentModel {

interface IContainer : IDisposable {
ComponentCollection Components { get; }
void Add(IComponent component);
void Add(IComponent component, string name);
void Remove(IComponent component);
}
}

Tramite questa interfaccia il designer host interagisce con i componenti trascinati sul container (form, UserControl, etc) ed allo stesso modo gli stessi componenti possono interagire con il designer host attraverso il loro container nella fase di design-time.



Nell'immagine sopra possiamo notare che la ralazione tra un componente ed il suo designer host è stabilita attraverso l'interfaccia ISite che, come abbiamo visto nel primo frammento di codice, è implementata come proprietà ad ogni Component per mezzo dell'interfaccia IComponent.

Quando un componente è aggiunto al container, il designer host crea un nuovo Site e lo connette al componente impostando la proprietà IComponent.Site. In questo modo viene impostata anche la proprietà IComponent.Site.Container che ci permette di accedere al contenitore del componente in modo rapido.


Facciamo un breve resoconto di questo primo articolo sul design-time ricapitolando quando detto per meglio capire quali sono le interfacce necessarie e quale ruolo svolgono all'interno del windows forms design.


  • IComponent: Ogni controllo o componente, per poter essere sul windows forms designer deve implementare questa interfaccia. Le classi quali Form, UserControl, ScrollableControl, ContainerControl la implementano indirettamente poichè derivano dalla classe Component che implementa IComponent direttamente.
  • IDesignerHost: Interfaccia implementata da Windows Forms Designer. Permette al designer-host (contenitore del disegno) di memorizzare i controlli che vengono creati ed aggiunti al contenitore(Form, UserControl etc) o trascinati su di esso. E' possibile ottenere un'istanza in questo modo: IDesignerHost host = this.Container as IDesignerHost;
  • IContainer: E' implementata in IDesignerHost come proprietà (Container) . Tramite essa è possibile aggiungere o rimuovere componenti ed accedervi attraverso la proprietà Components.
  • ISite: Interfaccia implememntata in ogni componente. Quando aggiungiamo un componente ad un container l'host-designer si preoccupa di conetterlo ad un nuovo Site. La proprietà DesignMode è fondamentale per impostare, via codice, determinate funzione da eseguire solo quando siamo in fase di design-time o run-time.

Seconda parte

Print | posted on Friday, March 9, 2007 1:45 AM

Comments have been closed on this topic.