I suggest 'de-composing' the dependencies here like this:
1. Form1 is the Main Form, the start-up Form.
2. Form2 is shown by Form1, but has no dynamic interaction with Form1
3. Form3 is shown by Form2, and changes in From3's TextBox should be immediately transmitted to Form1's Label. Form3 has no dynamic interaction with Form2
Note that you can view the relationship between Form1 and Form3 as either:
1. Form1 'observes/monitors' what happens in Form3, and updates itself. To 'observe' Form1 needs:
a. a reference to give it access to Form3's TextBox
b. a way to know when the Text on Form3's TextBox changes.
2. or, Form3 'publishes' its TextBox text as it changes, and Form1 'subscribes to the publishing event. For that to happen Form3 must define a 'publicly' visible event that Form1 can subscribe to.
Finally, a qualitatively different approach could be taken by moving all the events, and interactions, between all Forms into a special Class which will handle them, and which will expose Controls and Methods in a more general way. Perhaps think here about the role of the 'Controller' in the MVC paradigm.
One interesting 'dilemma' in this type of problem is that in order to 'hook-up' events, for Form interaction: those Forms need to be not just instantiated ... by new Form#n() ... but actually loaded and shown.
In this particular case, your design, evidently, demands the Forms not be shown until the user has taken some action.
So even if, for example, you create a public property of type TextBox on Form3, until Form3 is shown, you cannot access the actual TextBox control until Form3 is shown. And, nope, you cannot use a 'trick' like setting Form3.Visible = false, and then using 'Show, or 'ShowModal.
However, here's what you can do ... yes, at last, the simple solution, but with a slight hackish smell ...
Form2 f2;
Form3 f3;
private void Form1_Load(object sender, EventArgs e)
{
f2 = new Form2();
f3 = new Form3();
f2.SuspendLayout();
f2.Show();
f2.Visible = false;
f2.ResumeLayout();
f3.SuspendLayout();
f3.Show();
f3.Visible = false;
f3.ResumeLayout();
f2.f2Button.Click += new EventHandler(f2Button_Click);
f3.f3TextBox.TextChanged += new EventHandler(f3TextBox_TextChanged);
}
private void button1_Click(object sender, EventArgs e)
{
f2.ShowDialog();
}
private void f2Button_Click(object sender, EventArgs e)
{
f3.ShowDialog();
}
private void f3TextBox_TextChanged(object sender, EventArgs e)
{
label1.Text = f3.f3TextBox.Text;
}
Looking at the above code as one way to achieve a solution, you should then figure out for yourself exactly how Form2 'exposes' its Button, and Form3 'exposes' its TextBox.
Technically this solution 'injects' event handlers into Form2 and Form3: for that to happen, keep in mind those Forms have to be not just instantiated by 'new,' but created.
In my humble opinion, cases like this take you to the edge where a more general solution starts being worth the struggle, and by that I mean formalizing all event management and Form interaction into a class, which is probably static, and delegating all events into that class which then 'routes' and 'dispatches' them.
best, Bill