Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: spicklesОтветов: 3

Я изучаю обработчики событий и делегатов. У меня есть одна форма с 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);

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

eventsdelegatesevent-handling

Ответы

Ответ 1 · рейтинг 5 · digEmAll

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

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

Ответ 2 · рейтинг 1 · ispiro

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

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...
}

Ответ 3 · Eric H

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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы