web-dev-qa-db-fra.com

Convertir l'objet émetteur dans le gestionnaire d'événements à l'aide de GetType ().

J'ai un gestionnaire d'événements pour une zone de texte ainsi que pour un RichTextBox . Le code est identique, mais

Dans le gestionnaire n ° 1, je fais:

RichTextBox tb = (RichTextBox)sender

Dans le gestionnaire n ° 2 en conséquence:

TextBox tb = (TextBox)sender

Ce faisant, je peux entièrement manipuler le contrôle d’envoi .. Ce que je veux savoir, c’est comment puis-je convertir l’envoi en objet Textbox ou RichTextbox selon son type,

sender.GetType().Name

puis créez le contrôle au moment de l'exécution et utilisez-le. De cette façon, je n'ai besoin que d'une seule fonction de gestionnaire d'événements: moins de code, moins d'erreurs, plus facile à gérer et DRY :-)

21
tfl

Selon les propriétés dont vous avez besoin, vous pouvez convertir l'expéditeur en TextBoxBase car les deux propriétés TextBox et RichTextBox héritent toutes les deux de cette sous-classe.

3
Kieron

Vous n'avez jamais à lancer. J'avais l'habitude de penser de la même façon quand j'ai commencé, ce "motif" est incorrect et pas vraiment logique.

Votre meilleur pari est d'utiliser quelque chose comme:

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

Je sais que c'est un très vieux message, mais dans Framework 4, vous pouvez utiliser l'expéditeur comme contrôle:

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

Notez que vous pouvez uniquement référencer des contrôles communs à tous les contrôles (par exemple, Texte).

6
Mark Kram
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";
}
4
Chris S

Le casting ne peut être fait qu'au moment de la compilation et vous devez donc connaître les types que vous souhaitez utiliser au moment de la compilation. Un type d'exécution (tel que retourné par GetType ()) ne peut donc pas être utilisé lors de la conversion.

Si vous recherchez un polymorphisme, vous pouvez accéder à la propriété Name par réflexion. Je n’irais pas de cette façon mais pour pouvoir réutiliser des gestionnaires d’événements. 

Si vous voulez un typage fort, une classe de base commune ou une interface commune aux deux expéditeurs est la seule solution.

3
Peter Lillevold

Plutôt que le nom du type, vous pouvez utiliser ' is '.

Si vous voulez juste connaître le type et n'avez pas besoin d'une référence d'objet:

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

Cependant, vous voulez généralement que l'objet: C # 7 a une syntaxe Nice qui vous permet de tester et d'obtenir la valeur inline:

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

Vous pouvez également utiliser une variable temporaire en-ligne pour gérer la conversion pour vous.

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

Si le code est identique, avez-vous besoin de vous en soucier? Je me demande si le casting de Control ne vous donnerait pas tout ce dont vous avez besoin ...

Un gestionnaire complexe n'est pas nécessairement meilleur que plusieurs gestionnaires simples. De toute façon, si vous devez emprunter cette route, "comme"/"est" est préférable (cela ne dépend pas des chaînes, etc.):

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

Version générique du code ci-dessus:

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

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

Utilisé comme:

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

Pas parfait, mais pratique.

0
Josh

si vous ne voulez pas répéter le code, vous pouvez transtyper les deux contrôles, refactoriser les actions communes en une méthode séparée qui prend TextBoxBase en argument. Et dans vos gestionnaires d'événements, convertissez les contrôles en System.Windows.Forms.TextBoxBase car les deux contrôles sont dérivés de TexbBoxBase et appellent la méthode.

Remarque Si vous avez besoin des propriétés spécifiques de l'un de ces contrôles, cette refactorisation ne fonctionnera pas.

0
gk.