Приведение объекта-отправителя в обработчик событий с использованием GetType (). Name - PullRequest
21 голосов
/ 11 марта 2009

У меня есть обработчик событий для текстового поля, а также для RichTextBox. Код идентичен, но

В обработчике # 1 я делаю:

RichTextBox tb = (RichTextBox)sender

В обработчике # 2 соответственно:

TextBox tb = (TextBox)sender

Таким образом, я могу полностью манипулировать элементом управления отправкой. Я хочу знать, как я могу привести отправляющий объект к Textbox или RichTextbox в соответствии с его типом, используя

sender.GetType().Name

, а затем создайте элемент управления во время выполнения и работайте с ним. Таким образом, мне нужна только одна функция обработчика событий: меньше кода, меньше ошибок, проще в обслуживании и СУХОЙ: -)

Ответы [ 10 ]

29 голосов
/ 11 марта 2009

Вам никогда не придется разыгрывать. Когда я начинал, я думал так же, этот «шаблон» неверен и не совсем логичен.

Лучше всего использовать что-то вроде:

if (sender is TextBox)
{
  TextBox tb = (TextBox)sender;
}
else if (sender is RichTextBox)
{
  RichTextBox rtb = (RichTextBox)sender;
}
else
{
  // etc
}
6 голосов
/ 08 июля 2012

Я знаю, что это очень старый пост, но в Framework 4 вы можете использовать отправителя в качестве элемента управления:

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

Обратите внимание, что вы можете ссылаться только на элементы управления, общие для всех различных элементов управления (т. Е. На текст).

4 голосов
/ 11 марта 2009
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";
}
3 голосов
/ 11 марта 2009

В зависимости от того, какие свойства вам нужны, вы можете преобразовать отправителя как TextBoxBase, так как и TextBox, и RichTextBox оба наследуют от этого подкласса.

3 голосов
/ 11 марта 2009

Приведение может быть выполнено только во время компиляции, и поэтому вам нужно знать типы, которые вы хотите преобразовать во время компиляции. Поэтому тип времени исполнения (возвращаемый GetType ()) не может использоваться при приведении.

Если вы ищете полиморфизм, вы можете получить доступ к свойству Name через рефлексию. Я бы не пошел таким путем, просто чтобы иметь возможность повторно использовать обработчики событий.

Если вы хотите строгую типизацию, единственный базовый класс или интерфейс для двух отправителей - единственный путь.

2 голосов
/ 11 марта 2009

Вместо имени типа, которое вы могли бы использовать, равно .

Если вы просто хотите знать тип и вам не нужна ссылка на объект:

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

Однако, как правило, вы хотите, чтобы объект: C # 7 имеет хороший синтаксис, который позволяет вам тестировать и получать значение inline:

if (sender is RichTextBox richTextBox)
{
    richTextBox.Text = "I am rich";
}
else if (sender is TextBox textBox)
{
    textBox.Text = "I am not rich";
}
1 голос
/ 06 июля 2017

Вы также можете использовать встроенную временную переменную, чтобы обрабатывать приведение для вас.

if (sender is RichTextBox tb)
{
    // ... //
} 
else if (sender is TextBox tb)
{
    // ... //
}
0 голосов
/ 09 октября 2013

Общая версия вышеуказанного кода:

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

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

Используется как:

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

Не идеально, но удобно.

0 голосов
/ 11 марта 2009

Если вы не хотите повторять код, то вы можете привести оба элемента управления, рефакторинг общих действий в отдельный метод, который принимает TextBoxBase в качестве аргумента. И в ваших обработчиках событий преобразуйте элементы управления в System.Windows.Forms.TextBoxBase, поскольку оба элемента управления являются производными от TexbBoxBase и вызывают метод.

Обратите внимание: если вам нужны конкретные свойства любого из этих элементов управления, то этот рефакторинг не будет работать.

0 голосов
/ 11 марта 2009

Если код идентичен, вам нужно позаботиться? Интересно, если бы приведение к Control не дало бы вам всего, что вам нужно ...

Один сложный обработчик не обязательно лучше, чем несколько простых обработчиков. В любом случае, если у вас есть для перехода по этому маршруту, предпочтительнее использовать «as» / «is» (это не зависит от строк и т. Д.):

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