objeto emissor escalado para manipulador de eventos usando GetType (). Nome

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

  •  10-07-2019
  •  | 
  •  

Pergunta

Eu tenho um manipulador de eventos para uma caixa de texto, bem como para um RichTextBox. O código é idêntico, mas

Em manipulador # 1 i fazer:

RichTextBox tb = (RichTextBox)sender

Em manipulador nº 2 em conformidade:

TextBox tb = (TextBox)sender

Se o fizer, eu posso manipular totalmente o controle de envio. O que eu quero saber é como posso converter o objeto enviar para caixa de texto ou RichTextbox acordo com seu tipo usando

sender.GetType().Name

e, em seguida, criar o controle em tempo de execução e trabalhar com ele. Dessa forma, eu só preciso de função de manipulador de um evento: código menos, menos erros, mais fácil de manter e seca: -)

Foi útil?

Solução

Dependendo do que propriedades que você precisa, você poderia lançar o remetente como um TextBoxBase tanto como o TextBox e RichTextBox ambos herdar a partir dessa sub-classe.

Outras dicas

Você nunca tem que elenco. Eu costumava pensar da mesma maneira quando eu comecei, este 'padrão' é incorreto, e não realmente lógico.

Sua melhor aposta é usar algo como:

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

Eu sei que este é um post muito antiga, mas no Framework 4, você pode lançar o remetente como um controle:

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

Note que você só são capazes de controles de referência que todos os controles diferentes têm em comum (ou seja, texto).

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

Fundição só pode ser feito em tempo de compilação e, assim, você precisa saber os tipos que você deseja elenco para em tempo de compilação. Um tipo de tempo de execução (como retornado por GetType ()) pode, portanto, ser usado quando casting.

Se for polimorfismo que você está procurando você pode acessar a propriedade Nome através da reflexão. Eu não ir por esse caminho, embora apenas para ser capaz de reutilizar manipuladores de eventos.

Se você quiser tipagem forte, uma classe base comum ou interface dos dois remetentes é o único caminho a percorrer.

Ao invés do nome do tipo que você pode usar ' é '.

Se você só quer saber o tipo e não precisa de uma referência de objeto:

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

No entanto, você geralmente não quer que o objeto: C # 7 tem uma sintaxe agradável que permite que você teste e obter o valor em linha:

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

Você também pode usar uma variável inline-temporário para lidar com o elenco para você.

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

Se o código é idêntico, você precisa se preocupar? Pergunto-me se lançando para Control não iria dar-lhe tudo o que precisa ...

Um manipulador complexo não é necessariamente melhor do que vários manipuladores simples. De qualquer maneira, se você Have para percorrer este caminho "como" / "é" é preferível (que não é dependente de cordas etc):

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

Se você não quer repetir o código, então você pode lançar ambos os controles, refatorar as ações comuns a um método separado que leva TextBoxBase como um argumento. E em seus manipuladores de eventos converter os controles para System.Windows.Forms.TextBoxBase como ambos os controles são derivados do TexbBoxBase e chamar o método.

Observe se você precisa propriedades específicas de qualquer um desses controles, então isso não vai funcionar refatoração.

Versão genérica do código acima:

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

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

Usado como:

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

Não é perfeito, mas útil.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top