Как создать делегата для прослушивания всех текстовых полей в форме

Я изучаю обработчики событий и делегатов. У меня есть одна форма с 4 текстовыми полями и списком. Я хотел бы иметь делегата, который прослушивает изменения текстового поля в ЛЮБОМ из 4 полей. Метод, связанный с делегатом, будет просто методом, который принимает текстовое значение измененного текстового поля и добавляет его в качестве нового элемента списка. Мой вопрос заключается в том, как написать делегата для прослушивания всех текстовых полей, и когда я вызываю функцию для добавления элемента списка, как я могу передать объект текстового поля, поскольку я не буду явно знать, какой из них вызвал событие? Будет ли это содержаться в EventArgs e?

Вместо использования нескольких обработчиков событий:

this.textBo1.TextChanged += txt_TextChanged;
this.textBo2.TextChanged += txt_TextChanged;
this.textBo3.TextChanged += txt_TextChanged;
this.textBo4.TextChanged += txt_TextChanged;

Я хотел бы что-то вроде:

public delegate ListenToTextBoxes(object sender, EventArgs e);

Возможно, это не имеет смысла, так как я новичок в делегатах, но мне кажется разумным, что я должен иметь возможность заставить одного делегата слушать элементы управления текстовым полем в целом, а затем, когда он вызывает событие, я бросаю отправителя объекта и получить текст текстового поля. Но как мне создать делегата, чтобы он прослушивал ТОЛЬКО текстовые поля или другие типы элементов управления?


person spickles    schedule 29.02.2012    source источник


Ответы (3)


Как насчет чего-то подобного?

// form constructor
public MyForm()
{
   InitializeComponent();
   this.textBo1.TextChanged += txt_TextChanged;
   this.textBo2.TextChanged += txt_TextChanged;
   this.textBo3.TextChanged += txt_TextChanged;
   this.textBo4.TextChanged += txt_TextChanged;
}

// event handler
void txt_TextChanged(object sender, EventArgs e)
{
   var textBox = (TextBox)sender;
   this.myList.Add(textBox.Text);
}

EDIT:
(согласно обновлению вопроса)

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

public MyForm()
{
    InitializeComponent();

    // EventHandler is defined as:
    // delegate void EventHandler(object sender, EventArgs e)
    // so its signature is equal to your delegate:
    // delegate void ListenToTextBoxes(object sender, EventArgs e);
    // Hence, if you receive that delegate from somewhere out, you can pass it
    // to TextChange events
    var myDelegate = new EventHandler(txt_TextChanged);

    this.textBox1.TextChanged += myDelegate;
    this.textBox2.TextChanged += myDelegate;
    this.textBox3.TextChanged += myDelegate;
    this.textBox4.TextChanged += myDelegate;
}

Проблема в том, что вам нужно подписаться на событие TextChanged для каждого элемента управления TextBox, нет волшебного способа сказать "зарегистрировать все события TextBox.TextChange для этого делегата".
Но если вы уверены, что все текстовые поля, которые вы хотите зарегистрировать, являются дочерними элементами этого элемента управления, вы можете использовать цикл, например :

public MyForm()
{
    InitializeComponent();
    var myDelegate = new EventHandler(txt_TextChanged);
    foreach (var ctrl in this.Controls)
    {
        var txtBox = ctrl as TextBox;
        if (txtBox != null)
            txtBox.TextChanged += myDelegate;
    }
}
person digEmAll    schedule 29.02.2012
comment
Хорошо, приведение объекта-отправителя имеет смысл. Что мне все еще нужно, так это возможность создать одного делегата для ответа на все текстовые поля, а не несколько строк добавления обработчиков событий. Могу ли я сделать что-то вроде:‹br/› открытый делегат ListenToTextBox(TextBox textBox); - person spickles; 29.02.2012
comment
@spickles: Ммм, я не понимаю ... делегат - это, скажем, указатель на метод. Здесь вы передаете 4 делегата, указывающих на один и тот же метод. Что ж, если хотите, вы можете создать только один обработчик и передать его 4 событиям, но это не сильно изменит ситуацию. В любом случае, вероятно, я не понимаю, не могли бы вы дать больше информации, например, псевдокоды или что-то в этом роде? (изменить основной вопрос) - person digEmAll; 29.02.2012
comment
@spickles: Кстати, я предполагаю, что вы используете WinForms, это правильно? - person digEmAll; 01.03.2012
comment
@spickles: отредактировано. Я надеюсь, что это помогает. Кстати, случайно ли ваш делегат перешел откуда-то из вашей формы? - person digEmAll; 01.03.2012
comment
Выглядит неплохо. Я могу это сделать. Я не делегирую вне формы. Я предполагаю, что мне придется использовать Threading и некоторые классы/объекты для хранения данных между формами, если это то, что я хотел сделать? Спасибо за вашу помощь!! - person spickles; 01.03.2012
comment
@spickles: многопоточность + формы требуют тщательного управления. Я предлагаю вам использовать класс BackgroundWorker, чтобы избежать многих проблем с потоками в winforms;) - person digEmAll; 01.03.2012

Используйте «отправитель». Вот пример:

textBox1.Click += AllTextBoxes_Click;
textBox2.Click += AllTextBoxes_Click;

void AllTextBoxes_Click(object sender, EventArgs e)
{
    TextBox tb = sender as TextBox;
    tb.Text = "Clicked here";
}

Из-за обновленного вопроса:

public Form1()
{
    InitializeComponent();
    Listen(this);
}    

void Listen(Control ctrl)
{
    foreach (Control ctrl2 in ctrl.Controls)
    {
        if (ctrl2 is TextBox) (ctrl2 as TextBox).TextChanged += tb_TextChanged;
        foreach (Control ctrl3 in ctrl2.Controls) Listen(ctrl3);
    }
}

void tb_TextChanged(object sender, EventArgs e)
{
    //Do things...
}
person ispiro    schedule 29.02.2012
comment
Спасибо за ваш вклад, я ценю это! - person spickles; 01.03.2012

Вы можете интуитивно понять другие ответы, что sender является объектом, вызывающим событие (одно из ваших четырех текстовых полей, когда событие прикреплено к Click), однако для подробного объяснения определения отправителя я бы предложил КАК: определить отправителя события без использования свойства Control.Name

person Eric H    schedule 29.02.2012
comment
Спасибо за ваш вклад, я ценю это! - person spickles; 01.03.2012