2010-11-16 10 views
7

Devo creare un componente non visivo, FooComponent, che eseguirà una gestione per tutti i controlli di tipo Bar che risiede nel suo modulo.Componente .NET (non visivo)

Ho i seguenti vincoli:

  1. Il FooComponent può essere aggiunto solo alle forme.
  2. È consentito un solo FooComponent per modulo.
  3. FooComponent deve registrarsi all'evento di chiusura del modulo e quando viene attivato e ad alcune funzioni su tutti gli Bar e inviato il valore e.Cancel in base ai valori restituiti.

I punti n. 1 e n. 2 devono essere applicati in fase di esecuzione e in fase di progettazione. La registrazione degli eventi n. # 3 deve essere eseguita automaticamente e non dagli utenti di FooComponent.

Ho cercato Google e MSDN per qualche aiuto e ho letto sulle classi Component e ComponentDesigner, ma non ho trovato nulla per il salvataggio.

Cosa devo fare?

+0

Penso che si possa guardare CodeDomSerializer (http://msdn.microsoft.com/en-us/library/system.componentmodel.design.serialization.codedomserializer.aspx). Potrebbe essere la soluzione migliore. – PHeiberg

+0

@PHeiberg: Grazie –

risposta

3

(1) Per controllare che il componente possa essere aggiunto a un modulo, utilizzare un costruttore FooComponent che ha passato un modulo e non definire il costruttore predefinito. Si chiama come:

FooComponent component = new FooComponent(this); 

dove il componente viene creato all'interno del modulo stesso. Non definendo il costruttore predefinito, questo:

FooComponent component = new FooComponent(); 

non verrà compilato.


(2) esporre una proprietà FooComponent sul modulo stesso, e nel costruttore del FooComponent, impostare il FooComponent per this form passata.


(3) Stessa cosa, nel costruttore per il FooComponent, registrare con l'evento di chiusura per il modulo che avete passato


mettere tutto insieme e si ottiene:

public class MyForm : Form { 
    public FooComponent OwnedComponent { get; set; } 
} 


public class FooComponent { 

    public FooComponent (MyForm OwnerForm) { 
     OwnerForm.OwnedComponent = this; 
     OwnerForm.FormClosing += MyCallback; 
    } 

    private void MyCallback(object sender, FormClosingEventArgs e) { 
     ... 
    } 

} 



MODIFICA
Sfortunatamente, se avete bisogno di e costruttore predefinito, e se deve essere un vero componente drop-on-the-form, non c'è modo di far rispettare che un componente viene creato solo su un modulo o che il modulo ha solo un'istanza del componente (non da all'interno del componente, comunque).

Il problema è duplice:
(1) Eliminazione di un componente non aggiungere il componente alla forma, si aggiunge alla collezione del modulo components. Quindi, anche se potresti ottenere un handle per il genitore/proprietario, non sarà mai una forma.

(2) Come indicato da Neil, l'eliminazione di un componente in un modulo chiama il costruttore predefinito, che non passa alcun parametro e, ovviamente, nessuna delle proprietà del componente (come il sito o il contenitore) viene popolata.


Possibilmente utile: Un componente può essere progettato per essere avvisati quando viene creato in due modi:

(1) Implementando un costruttore che accetta un parametro IContainer. Quando il componente viene rilasciato su un modulo, il codice generato chiamerà invece questo costruttore. Tuttavia, lo farà solo in fase di runtime, non in fase di progettazione. Ma il contenitore sarà un handle per la raccolta components del modulo.

public FooComponent(IContainer container) {...} 

(2) Implementando ISupportInitialize. Quando il componente viene rilasciato su un modulo, il codice generato chiamerà inoltre BeginInit() e EndInit(). In EndInit(), è possibile accedere a proprietà come Site e Container. Anche in questo caso, lo si otterrà solo in fase di runtime, non in fase di progettazione, e lanciando un'eccezione qui non impedirà la creazione del componente.

Vecchi, ma eccellenti articoli su componenti e controlli da MSDN Magazine di Michael Weinhardt e Chris Sells.
April 2003 Building Windows Forms Controls and Components with Rich Design-Time Features
May 2003 Building Windows Forms Controls and Components with Rich Design-Time Features, Part 2

Questi sono ora file di aiuto CHM. Dovrai sbloccare la pagina delle proprietà del file per abilitare la lettura dei contenuti dopo il download.

+0

Lo svantaggio di non consentire un costruttore vuoto è che non si sarà in grado di utilizzare il controllo in fase di progettazione. –

+0

L'OP dice che è un componente non visivo che sta creando, quindi questo non dovrebbe essere un problema. Il costruttore intendo è il costruttore di FooComponent ... Chiarirò che nella domanda –

+0

vedo cosa intendi ... se letteralmente significa un 'componente 'che vuole trascinare e rilasciare il modulo, allora sei giusto, deve avere un costruttore predefinito. –

1

Non credo sia possibile definire esattamente cosa può contenere una classe contenuta. Non ho mai visto un'istanza in cui ho ricevuto un errore (o anche un avvertimento) per l'impostazione di una proprietà di un tipo in un altro, anche in WinForms.

Qualcosa che potresti essere in grado di fare è definire un antenato derivato da un modulo per i tuoi moduli che contiene un riferimento al tuo FooComponent (visibile internamente), inizializza uno su istanziazione e allega i gestori. Per ottenere i migliori risultati, dovrebbe essere senza parametri e l'unico sovraccarico del costruttore, quindi costituisce la base per qualsiasi costruttore che i tuoi utenti generano. Quindi, crea una regola per la casa che deriva dalla tua classe di antenato e non direttamente da Form (potresti essere in grado di utilizzare uno strumento di controllo del codice come FxCop o simile per imporre ciò quando il codice è impegnato per il controllo del codice sorgente). I tuoi utenti ora ottengono un FooComponent in ogni modulo che creano, non possono crearne di propri (è interno e dovrebbero trovarsi in un altro progetto con il tuo antenato di Form) e non devono fare altro che derivare dalla nuova classe per far sì che le loro forme si comportino il modo in cui vuoi

+0

Ho bisogno che questo sia supportato in fase di progettazione, sai comunque di ottenere il # 3 in fase di progettazione? –

1

Stai chiedendo molto. In generale, rendere i componenti consapevoli della forma in cui vengono rilasciati è piuttosto difficile. This answer può aiutarti a implementare il gestore di eventi. È necessario implementare ISupportInitialize per ottenere la chiamata EndInit() per impostare il gestore eventi.

Anche la prevenzione dei multipli è abbastanza difficile, posso solo pensare a un designer personalizzato che possa intervenire abbastanza presto per impedire che venga aggiunto il secondo.