Прослушивание событий в основной форме из другой формы в C#

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

У меня также есть другая форма в приложении. В любой момент времени может быть запущено несколько экземпляров этой второй формы.

Я хотел бы, чтобы каждый экземпляр этой второй формы прослушивал обработчик событий в основной форме и обновлял элементы управления в своем экземпляре второй формы.

Как бы я это сделал?

Вот пример кода. Я хочу, чтобы информация из обработчика событий the_timer_Tick обновляла каждый экземпляр SecondaryForm.

public partial class Form1 : Form
{
    Timer the_timer = new Timer();
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        the_timer.Tick += new EventHandler(the_timer_Tick);
        the_timer.Interval = 2000;
        the_timer.Enabled = true;
    }

    void the_timer_Tick(object sender, EventArgs e)
    {
        // I would like code in here to update all instances of SecondaryForm
        // that happen to be open now.
        MessageBox.Show("Timer ticked");
    }

    private void stop_timer_button_Click(object sender, EventArgs e)
    {
        the_timer.Enabled = false;
    }

    private void start_form_button_Click(object sender, EventArgs e)
    {
        SecondaryForm new_form = new SecondaryForm();
        new_form.Show();
    }
}

person Dave    schedule 04.03.2009    source источник


Ответы (3)


Рассмотрите возможность использования слабосвязанных событий. Это позволит вам связать классы таким образом, что они никогда не должны быть непосредственно осведомлены друг о друге. Блок приложения Unity поставляется с расширением под названием EventBroker. просто.

Вот кусочек сахара:

public static class EVENTS
{
    public const string UPDATE_TICKED = "event://Form1/Ticked";
}

public partial class Form1 : Form
{
    [Publishes(EVENTS.UPDATE_TICKED)]
    public event EventHandler Ticked; 

    void the_timer_Tick(object sender, EventArgs e)
    {
        // I would like code in here to update all instances of SecondaryForm
        // that happen to be open now.
        MessageBox.Show("Timer ticked");
        OnTicked();
    }

    protected virtual void OnTicked()
    {
        if (Ticked == null) return;
        Ticked(this, e);
    }
}

public partial class SecondaryForm : Form
{
    [SubscribesTo(EVENTS.UPDATE_TICKED)]
    private void Form1_Ticked(object sender, EventHandler e)
    {
        // code to handle tick in SecondaryForm
    }
}

Теперь, если вы создадите оба этих класса с помощью Unity, они будут автоматически связаны друг с другом.

Обновить

Более новые решения используют шину сообщений для обработки слабо связанных событий. См. http://masstransit-project.com/ или http://nimbusapi.github.io/ в качестве примера.

person Michael Meadows    schedule 04.03.2009
comment
@ Okuma.Scott Предоставил еще одну ссылку, а также обновленную информацию о том, как я теперь обрабатываю слабосвязанные события. Я предпочитаю шину сообщений в памяти. Это позволяет использовать горизонтальный масштаб. Nimbus использует шину сообщений Azure, а Mass Transit использует RabbitMQ. - person Michael Meadows; 11.12.2014

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

private void start_form_button_Click(object sender, EventArgs e)
{
    SecondaryForm new_form = new SecondaryForm(this);
    new_form.Show();
}

В SecondaryForm.cs:

public SecondaryForm(ISomeView parentView)
{
    parentView.SomeEvent += .....
}
person Kjetil Watnedal    schedule 04.03.2009

person    schedule
comment
Не забудьте удалить обработчик событий при закрытии второй формы, иначе у вас может быть утечка ссылок... - person Rowland Shaw; 04.03.2009
comment
Разве все ваши ссылки на SecondForm не должны быть SecondaryForm? И как бы выглядел SomeEvent в основной форме, которую я разместил? - person Dave; 04.03.2009
comment
Да, я имею в виду SecondForm = SecondaryForm. Например, вы можете сделать Timer общедоступным или создать свойство для доступа к нему и прослушивать не события FistForm, а события таймера: смотрите мой код, я его отредактирую. - person abatishchev; 04.03.2009
comment
Я получаю Ссылка на объект требуется для нестатического поля, метода или свойства «TestApp.SecondaryForm.Timer_Tick(object, System.EventArgs)», когда я пытаюсь назначить обработчик событий для the_timer.Tick += new EventHandler (ВторичнаяФорма.Timer_Tick); - person Dave; 04.03.2009
comment
Извините моя ошибка. Используйте EventHandler(secondForm.Timer_tick) вместо SecondForm.Timer_tick. Также я изменил свойство для Timer. - person abatishchev; 04.03.2009