Trasmetti l'oggetto mittente nel gestore eventi utilizzando GetType (). Nome

StackOverflow https://stackoverflow.com/questions/634112

  •  10-07-2019
  •  | 
  •  

Domanda

Ho un gestore di eventi per una casella di testo e per un RichTextBox. Il codice è identico, ma

Nel gestore n. 1 che faccio:

RichTextBox tb = (RichTextBox)sender

Nel gestore n. 2 di conseguenza:

TextBox tb = (TextBox)sender

In questo modo posso manipolare completamente il controllo di invio. Quello che voglio sapere è come posso trasmettere l'oggetto di invio a Textbox o RichTextbox in base al suo tipo usando

sender.GetType().Name

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

È stato utile?

Soluzione

A seconda delle proprietà necessarie, è possibile eseguire il cast del mittente come TextBoxBase poiché sia ??TextBox che RichTextBox ereditano entrambi da quella sottoclasse.

Altri suggerimenti

Non devi mai lanciare. Pensavo allo stesso modo quando ho iniziato, questo "modello" non è corretto e non è logico.

La tua scommessa migliore è usare qualcosa come:

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

So che questo è un post molto vecchio, ma in Framework 4 puoi lanciare il mittente come controllo:

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

Nota che puoi solo fare riferimento ai controlli che tutti i diversi controlli hanno in comune (ad es. Testo).

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";
}

Il cast può essere eseguito solo in fase di compilazione e quindi è necessario conoscere i tipi su cui si desidera eseguire il cast in fase di compilazione. Un tipo di runtime (come restituito da GetType ()) non può pertanto essere utilizzato durante il cast.

Se stai cercando il polimorfismo, puoi accedere alla proprietà Name tramite la riflessione. Non vorrei andare così solo per poter riutilizzare i gestori di eventi.

Se si desidera digitare in modo forte, una classe di base comune o un'interfaccia sui due mittenti è l'unica strada da percorrere.

Invece del nome del tipo che potresti usare ' è '.

Se vuoi solo conoscere il tipo e non hai bisogno di un riferimento a un oggetto:

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

Comunque generalmente vuoi l'oggetto: C # 7 ha una bella sintassi che ti permette 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";
}

Puoi anche usare una variabile inline-temporanea per gestire il cast per te.

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

Se il codice è identico, devi preoccuparti? Mi chiedo se il casting in Control non ti darebbe tutto ciò di cui hai bisogno ...

Un gestore complesso non è necessariamente migliore di molti gestori semplici. In entrambi i casi, se devi seguire questa rotta, "poiché" quot / / "è " è preferibile (non dipende da stringhe ecc.):

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

se non si desidera ripetere il codice, è possibile eseguire il cast di entrambi i controlli, riformattare le azioni comuni in un metodo separato che utilizza TextBoxBase come argomento. E i gestori di eventi convertono i controlli in System.Windows.Forms.TextBoxBase poiché entrambi i controlli sono derivati ??da TexbBoxBase e chiamano il metodo.

Nota Se hai bisogno di proprietà specifiche di uno di questi controlli, questo refactoring non funzionerà.

Versione generica del codice sopra:

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

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

Utilizzato come:

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

Non perfetto, ma utile.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top