2009-03-11 8 views
19

Tengo un controlador de eventos para un cuadro de texto así como para un cuadro de texto enriquecido. El código es idéntico, peroEnviar el objeto remitente en el controlador de eventos utilizando GetType(). Nombre

En manejador # 1 que hago:

RichTextBox tb = (RichTextBox)sender 

En manejador # 2 en consecuencia:

TextBox tb = (TextBox)sender 

Si lo hace, puedo manipular completamente el control de envío. Lo que quiero saber es ¿cómo puedo convertir el objeto de enviar al cuadro de texto o RichTextbox según su tipo usando

sender.GetType().Name 

y luego crear el control en tiempo de ejecución y trabajar con él. De esa manera yo sólo necesito función de controlador de un evento: menos código, menos errores, más fácil de mantener y seco :-)

+0

¿Puede dar un ejemplo de un método o propiedad polimórfica que se comparte entre dos tipos de este tipo? y sin embargo, no está expuesto por una interfaz común? – AnthonyWJones

Respuesta

3

En función de las propiedades que necesitan, en que pudieras jugar el remitente como TextBoxBase, ya que tanto el TextBox como el RichTextBox heredan de esa subclase.

+0

que parece prometedor Voy a intentarlo ... – tfl

+0

Espero que funcione (: – 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

Más que el nombre del tipo que se puede utilizar 'es', si lo que desea saber la escriba y no necesita una referencia de objeto.

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

Editar: sin embargo, como se señala en un comentario, por lo general, no quiere que el oObject: C# 7 tiene una buena sintaxis que permite poner a prueba y obtener el valor en línea:

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

que parece ser el mejor compromiso - gracias – tfl

+1

Esto está bien, pero la sugerencia de @Chris es mejor. Como va a hacer algo con los objetos inmediatamente, le ahorrará un lanzamiento extra. –

3

Fundición solo se puede hacer en tiempo de compilación y, por lo tanto, debe conocer los tipos a los que desea enviar en tiempo de compilación. Por lo tanto, un tipo de tiempo de ejecución (como lo devuelve GetType()) no se puede usar cuando se realiza el envío.

Si está buscando el polimorfismo, puede acceder a la propiedad Name a través de la reflexión. No iría de esa manera sin embargo solo para poder reutilizar manejadores de eventos.

Si desea escribir fuerte, una clase base común o interfaz en los dos remitentes es la única manera de hacerlo.

28

Nunca tiene que emitir. Solía ​​pensar de la misma manera cuando comencé, este 'patrón' es incorrecto, y no es realmente lógico.

Su mejor opción es usar algo como:

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

En realidad estás lanzando una vez que has determinado el tipo del objeto, por lo que * tienes que * lanzar, pero esta es definitivamente la manera correcta de hacerlo ya que no depende de la reflexión (lenta). – idmadj

0

Si el código es idéntico, lo que necesita para cuidar? Me pregunto si el casting a Control no le daría todo lo que necesita ...

Un controlador complejo no es necesariamente mejor que varios manejadores simples. De cualquier manera, si usted tiene a seguir este camino "como"/"es" es preferible (que no depende de cuerdas, etc.):

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

si no desea repetir el código, puede lanzar ambos controles, refactorizar las acciones comunes a un método separado que toma TextBoxBase como argumento. Y en su evento, los manejadores convierten los controles a System.Windows.Forms.TextBoxBase ya que ambos controles se derivan de TexbBoxBase y llaman al método.

Tenga en cuenta Si necesita propiedades específicas de cualquiera de estos controles, esta refactorización no funcionará.

6

Sé que esto es un post muy antiguo pero en Framework 4 que puede emitir el emisor como control:

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

Nota que sólo son capaces de hacer referencia a controles que todos los diferentes controles tienen en común (es decir, texto).

0

versión genérica del código anterior:

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

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

utilizan como:

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

No es perfecto, pero es práctico.

0

También puede usar una variable temporal en línea para manejar el reparto por usted.

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