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

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

  •  10-07-2019
  •  | 
  •  

Question

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 le fais:

RichTextBox tb = (RichTextBox)sender

Dans le gestionnaire n ° 2 en conséquence:

TextBox tb = (TextBox)sender

Ce faisant, je peux pleinement manipuler le contrôle d’envoi. Ce que je veux savoir, c'est comment puis-je convertir l'objet d'envoi en Textbox ou RichTextbox en fonction de son type avec

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: -)

Était-ce utile?

La solution

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

Autres conseils

Vous n'avez jamais à lancer. Je pensais de la même manière 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
}

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 ne pouvez référencer que les contrôles communs à tous les contrôles (par exemple, Texte).

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

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 qu’il est renvoyé 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 seule classe ou interface commune sur les deux expéditeurs est la seule solution.

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 possède une belle syntaxe 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";
}

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)
{
    // ... //
}

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

Un gestionnaire complexe n’est pas nécessairement meilleur que plusieurs gestionnaires simples. Quoi qu'il en soit, si vous devez emprunter cette voie, "tel que" / "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 */}
...

si vous ne voulez pas répéter le code, vous pouvez transtyper les deux commandes, 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 les propriétés spécifiques de l'un de ces contrôles sont nécessaires, le refactoring ne fonctionnera pas.

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top