2009-03-11 16 views
19

Ho un gestore eventi per una casella di testo e per un oggetto RichTextBox. Il codice è identico, maTrasmetti oggetto mittente nel gestore eventi utilizzando GetType(). Nome

In handler # 1 che faccio:

RichTextBox tb = (RichTextBox)sender 

Nel gestore # 2 di conseguenza:

TextBox tb = (TextBox)sender 

In questo modo posso manipolare completamente il controllo di invio. Quello che voglio sapere è come Posso lanciare l'oggetto invio a Casella di testo o RichTextbox in base al tipo utilizzando

sender.GetType().Name 

e quindi creare il controllo in fase di esecuzione e lavorare con esso. In questo modo ho bisogno solo funzione di gestore di un evento: meno codice, meno errori, più facile da mantenere e DRY :-)

+0

Puoi fornire un esempio di un metodo o di una proprietà polimorfica condivisa tra due di questi tipi? eppure non è esposto da un'interfaccia comune? – AnthonyWJones

risposta

3

a seconda di cosa avete bisogno proprietà, in cui potresti giocare il mittente come TextBoxBase poiché sia ​​il TextBox sia il RichTextBox ereditano entrambi dalla sottoclasse.

+0

sembra promettente! Farò un tentativo ... – tfl

+0

Spero che funzioni (: – Kieron

4
RichTextBox textbox = sender as RichTextBox; 
if (textbox != null) 
{ 
    // do stuff as a rtb 
    textbox.Text = "I'm a rtb"; 
    return; 
} 

TextBox textbox = sender as TextBox; 
if (textbox != null) 
{ 
    // do stuff as a textbox 
    textbox.Text = "I'm a textbox"; 
} 
1

Piuttosto che il nome del tipo è possibile utilizzare 'è', se si desidera solo conoscere il digita e non ha bisogno di un riferimento a un oggetto.

if (sender is RichTextBox) 
{ 
    // ... 
} 
else if (sender is TextBox) 
{ 
    // ... 
} 

Edit: tuttavia, come sottolineato in un commento, in genere si desidera che l'oObject: C# 7 ha un bel sintassi che consente di testare e ottenere il valore in linea:

if (sender is RichTextBox richTextBox) 
{ 
    richTextBox.Text = "I am rich"; 
} 
else if (sender is TextBox textBox) 
{ 
    textBox.Text = "I am not rich"; 
} 
+0

che sembra essere il miglior compromesso - grazie – tfl

+1

Questo è ok ma il suggerimento di @Chris è migliore. Dal momento che stai andando a fare qualcosa con gli oggetti immediatamente ti salverà un cast extra. –

3

Casting può essere fatto solo in fase di compilazione e quindi è necessario conoscere i tipi che si desidera trasmettere in fase di compilazione. Pertanto, un tipo di runtime (come restituito da GetType()) non può essere utilizzato durante il casting.

Se è il polimorfismo che si sta cercando, è possibile accedere alla proprietà Name tramite reflection. Non andrei in questo modo solo per poter riutilizzare i gestori di eventi.

Se si desidera una forte digitazione, una sola classe base o interfaccia comune sui due mittenti è l'unica strada da percorrere.

28

Non devi mai trasmettere. Ero solito pensare allo stesso modo quando ho iniziato, questo "modello" non è corretto e non è logico.

La cosa migliore è usare qualcosa come:

if (sender is TextBox) 
{ 
    TextBox tb = (TextBox)sender; 
} 
else if (sender is RichTextBox) 
{ 
    RichTextBox rtb = (RichTextBox)sender; 
} 
else 
{ 
    // etc 
} 
+1

In realtà stai trasmettendo una volta determinato il tipo di oggetto, quindi * devi * eseguire il cast, ma questo è sicuramente il modo giusto per farlo in quanto non si basa su una riflessione (lenta). – idmadj

0

Se il codice è identico, avete bisogno di cure? Mi chiedo se il casting su Control non ti dia tutto ciò che ti serve ...

Un gestore complesso non è necessariamente migliore di molti semplici gestori. In entrambi i casi, se si dispone di di seguire questa strada "come"/"è" è preferibile (ma non dipende da corde etc.):

TextBox tb = sender as TextBox; 
if(tb!=null) {/* TextBox specific code */} 
... 
0

se non si desidera ripetere il codice, è possibile eseguire il cast di entrambi i controlli, rifattorizzare le azioni comuni in un metodo separato che accetta TextBoxBase come argomento. E nei gestori di eventi, converti i controlli in System.Windows.Forms.TextBoxBase poiché entrambi i controlli derivano da TexbBoxBase e chiamano il metodo.

Nota Se sono necessarie proprietà specifiche di uno di questi controlli, questo refactoring non funzionerà.

6

So che questo è un post molto vecchio, ma nel Framework 4 si può lanciare il mittente come un controllo:

Control cntrl = (Control)sender; 
cntrl.Text = "This is a " + sender.GetType().ToString(); 

Nota si è in grado di fare riferimento a controlli che tutti i diversi controlli hanno in comune solo (cioè testo).

0

versione generica del codice di cui sopra:

public static void CastAndUse<T>(object item, Action<T> action) where T : class 
{ 
    T thing = item as T; 

    if (thing != null) 
    { 
     action(thing); 
    } 
} 

Usato come:

CastAndUse(sender, new Action((foo) => foo = bar)); 

Non perfetto, ma a portata di mano.

0

È anche possibile utilizzare una variabile temporanea incorporata per gestire il cast per te.

if (sender is RichTextBox tb) 
{ 
    // ... // 
} 
else if (sender is TextBox tb) 
{ 
    // ... // 
} 
Problemi correlati