Costruzione di custom controls con supporto a design time: Property Editor e Component Editor

2 pagine in totale: <<Indietro 1 [2]

Editor di componente

Avere a disposizione una form che permetta all'utente di settare più proprietà è una cosa che personalmente trovo molto comoda, anche perché, se fatti bene, questi editor rendono quasi inutile ricorrere alla versione HTML della progettazione (lo dico nonostante io faccia quasi tutto in HTML).

Il concetto logico con cui VS implementa questa feature è lo stesso di quello usato per gli UITypeEditor ma con qualcosa di nuovo.

Quando l'oggetto viene selezionato nel designer, l'editor cerca tra gli attributi del componente uno di nome Editor e utilizza i dati in esso contenuti per ottenere un riferimento alla classe che fa da ponte tra l'editor e la form. Questo attiva di default il bottone presente nel PE. Quando il bottone viene cliccato, viene chiamato il metodo EditComponent della classe "ponte", il quale si occupa di istanziare e visualizzare la form. C'è inoltre un secondo meccanismo che aggiunge delle funzionalità ricorrendo ai DesignerVerb . Quando l'utente clicca col tasto destro sul controllo, il designer cerca tra gli attributi del componente l'attributo Designer, di cui abbiamo parlato nel primo articolo. Se presente, utilizza la proprietà Verbs della classe indicata per avere una collection di azioni che appariranno sotto forma di voci nel menu contestuale. Inoltre queste voci appariranno anche in basso nel PE quando il controllo verrà selezionato.

Innanzitutto si deve creare la WindowsForm per settare le proprietà. Si aggiunge un costruttore che accetta in input il componente cosi da poter già inizializzare i campi con i  valori attuali e successivamente, in fase di chiusura, poter valorizzare le proprietà con i nuovi valori.

Il secondo passo consiste nel creare la classe "ponte" tra l'editor e la form. Questa classe deve ereditare da System.Windows.Forms.Design. WindowsFormsComponentEditor e implementare il metodo EditComponent .

  public class SMDivCompEditorBridge : WindowsFormsComponentEditor{
   public override bool EditComponent (System.ComponentModel.ITypeDescriptorContext context, object component, System.Windows.Forms.IWin32Window owner){
     SMDiv Comp = component as SMDiv;
     if (Comp == null) throw new ArgumentException("Invalid object");
 
      IServiceProvider site = Comp.Site;
      IComponentChangeService changeService = null;
      DesignerTransaction transaction = null;
      bool changed = false;

      try{
        if (site != null){
         IDesignerHost designerHost = (IDesignerHost)site.GetService(typeof(IDesignerHost));
         transaction = designerHost.CreateTransaction("Component editor");
         changeService = (IComponentChangeService)site.GetService(typeof(IComponentChangeService));
         if (changeService == null){
           try{
            changeService.OnComponentChanging(Comp, null);
           }
           catch (CheckoutException ex){
            if (ex == CheckoutException.Canceled) return false;
            throw ex;
           }
         }
        }

        try{
         SMDivCompEditorForm form = new SMDivCompEditorForm(Comp);
         if (form.ShowDialog(owner) == DialogResult.OK){
           changed = true;
         }
        }
        finally{
         if (changed && changeService != null) {
           changeService.OnComponentChanged(Comp, null, null, null);
         }
        }
      }
      finally{
        if (transaction != null){
         if (changed){
           transaction.Commit();
         }
         else{
           transaction.Cancel();
         }
        }
      }
      return changed;
     }
   }
  }

Questo metodo utilizza i servizi necessari all'editor, quali transazioni e notifiche di modifica del controllo, per istanziare e visualizzare la form. Il metodo ritorna un valore booleano che specifica se le proprietà sono state modificate nella form. Chi ha letto il libro di Nikhil Khotari sulla creazione dei controlli ASP.NET troverà questo codice sinistramente familiare.

Infine bisogna impostare l'attributo, a livello di controllo, Editor per collegare l'editor con la classe "ponte".

Editor(typeof(SMDivCompEditorBridge), typeof(ComponentEditor))

Come detto in precedenza, si possono aggiungere voci al PE ed al menu contestuale di un oggetto nel designer. Per fare questo, bisogna creare una classe che eredita da ControlDesigner ed eseguire l'override della proprietà Verbs .

  public class DesignTime : System.Web.UI.Design.ControlDesigner{
   public override DesignerVerbCollection Verbs{
     get {
      DesignerVerbCollection designerVerbs = null;
      if (designerVerbs == null) {
        designerVerbs = new DesignerVerbCollection();
        designerVerbs.Add(new DesignerVerb("Component editor", new EventHandler(this.OnCommand)));
      }
      return designerVerbs;
     }
   }

   private void OnCommand(object sender, EventArgs e){
     SMDivCompEditorBridge editor = new SMDivCompEditorBridge();
     editor.EditComponent(Component);
   }
  }

La proprietà ritorna una collection di DesignerVerb . Un DesignerVerb altro non è che una voce del menu contestuale. Nel costruttore del DesignerVerb che viene aggiunto, vanno specificati il testo da visualizzare e il delegate da invocare al click. Nel delegate viene chiamato il metodo EditComponent della classe "ponte", emulando il comportamento del clic sul bottone dell'editor di proprietà. In realtà i DesignerVerbs non sono utilizzati solo per le form di proprietà ma possono avere tanti altri usi. Si può emulare un Next Page - Prev Page per un controllo Tab, o come nel DataAdapter, testare i dati di ritorno dalle query. Per agganciare questa classe al controllo, bisogna aggiungere l'attributo Designer .

Designer(typeof(DesignTime))

Questo screenshoot mostra il DesignerVerb nel menu contestuale:

Questo secondo screenshot mostra il bottone sull'editor di proprietà per chiamare una form custom, risultato dell'attributo Editor sul controllo e, in basso, la voce aggiunta tramite DesignerVerb:

Qui vediamo la form per settare le proprietà Width ed Height contemporaneamente:

Conclusioni

In questo secondo articolo ho mostrato le tecniche per migliorare visivamente i controlli, ma anche per migliorarne la velocità e la semplicità d'uso. A differenza del precedente articolo, questo articolo è quasi completamente applicabile anche ai componenti creati per le WindowsForm. Questo perché gli attributi aggiunti e le classi implementate si interfacciano con l'editor di proprietà le cui API sono le stesse per tutti i tipi di progetti, mentre nel precedente articolo ci si interfacciava con le API dell'editor HTML di VS che ovviamente può accettare solo "markup language".

Nel prossimo articolo illustrerò come implementare un sistema di autocompletamento nella versione HTML di una pagina e il sistema di suggerimenti che VS visualizza quando si richiede l'autocompletamento durante la scrittura di codice C#.

Approfondimenti

2 pagine in totale: <<Indietro 1 [2]

Attenzione: Questo articolo contiene un allegato

Contenuti dell'articolo

Commenti
Dai un voto a questo articolo, ci aiuterà a migliorare il nostro sito (1 è il voto minimo, 5 il massimo).

Per procedere al rating dell'articolo devi essere autenticato.

Aggiungi un nuovo commento »»»
Per inserire un commento, devi registrarti alla nostra community.


TUTORIALS
TOP TEN ARTICOLI
NOTIFICHE

Iscriviti alla nostra newsletter nuoviarticoli per ricevere e-mail le notifiche!

Indirizzo e-mail:
PROVIDER ASP.NET 2.0

Seleziona il database per avere il web.config pronto per Membership, Roles e Profile API.



IN EVIDENZA
MISC