I have an application that has a main form and uses an event handler to process incoming data and reflect the changes in various controls on the main form. This works fine.
I also have another form in the application. There can be multiple instances of this second form running at any given time.
What I'd like to do is have each instance of this second form listen to the event handler in the main form and update controls on its instance of the second form.
How would I do this?
Here's some sample code. I want to information from the_timer_Tick event handler to update each instance of 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();
}
}
class SecondForm
{
private FirstForm firstForm;
public SecondForm()
{
InitializeComponent();
// this means unregistering on form closing, uncomment if is necessary (anonymous delegate)
//this.Form_Closing += delegate { firstForm.SomeEvent -= SecondForm_SomeMethod; };
}
public SecondaryForm(FirstForm form) : this()
{
this.firstForm = form;
firstForm.Timer.Tick += new EventHandler(Timer_Tick);
}
// make it public in case of external event handlers registration
private void Timer_Tick(object sender, EventArgs e)
{
// now you can access firstForm or it's timer here
}
}
class FirstForm
{
public Timer Timer
{
get
{
return this.the_timerl
}
}
public FirstForm()
{
InitializeComponent();
}
private void Button_Click(object sender, EventArgs e)
{
new SecondForm(this).ShowDialog(); // in case of internal event handlers registration (in constructor)
// or
SecondForm secondForm = new SecondForm(this);
the_timer.Tick += new EventHandler(secondForm.Timer_tick); // that method must be public
}
Consider using loosely coupled events. This will allow you to couple the classes in such a way that they never have to be directly aware of each other. The Unity application block comes with an extension called EventBroker that makes this very simple.
Here's a little lick of the sugar:
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
}
}
Now if you construct both of these classes using Unity, they will automatically be wired together.
Update
Newer solutions use message bus to handle loosely coupled events. See http://masstransit-project.com/ or http://nimbusapi.github.io/ as examples.
I guess you can make SecondaryForm take in the parent form in the constructor, and the add an event handler in the constructor.
private void start_form_button_Click(object sender, EventArgs e)
{
SecondaryForm new_form = new SecondaryForm(this);
new_form.Show();
}
In SecondaryForm.cs:
public SecondaryForm(ISomeView parentView)
{
parentView.SomeEvent += .....
}
来源:https://stackoverflow.com/questions/610313/listening-to-events-in-main-form-from-another-form-in-c-sharp