Transferring information between two forms, Part 3: Child to Child






4.94/5 (10 votes)
Questions here quite often ask "how do I send data from one form to another?" and I must have answered this a dozen times. So, a series of three tips to cover the process.
Introduction
It's a common problem. How do you transfer data between two forms in a Windows Forms application? And it's really easy to do. But...there are too many people out there that will tell you to just "make the control public
" and set the value. Unfortunately that's a very bad idea - and the proper way is not a lot more complex.
This could have been an article, but I wanted to keep it focussed (because this is information for a beginner and felt that a tip for each of the common transfers might work better.
So, a set of three Tips:
Part1: Parent to Child Transferring information between two forms, Part 1: Parent to Child[^]
- Covers transferring data from a Parent form to it's Child form when the Parent want's to.
- Covers transferring data from the Child to the Parent when the Child wants to.
- Covers transferring data from a Child to another Child when the first Child wants to.
Background
If "making the control public
" works, why is is it private
by default? Why not do that and move on? It's easy to do and it works!
The answer is that when you do that, you are exposing the internals of your form to the whole world - and that is not a good idea, because:
- It's against the principles of OOPs
- It locks the design of the two forms together - you can't change one form without considering it's effects on the other. Suppose you have a TextBox in a child, and you make it
public
. You now can't change it to any other control (or do anything with it at all, pretty much) because it might break the form that is using it. This makes your life a lot harder when you have a small change to make, because suddenly it's a small change to the child, and a massive set of changes to the parent. - When you make a control
public
, you don't just expose the field you want: myTextBox.Text. Oh, no - you expose them all.Font
, Size
,Location
,BackColor
, then lot. And there is nothing stopping any external class from changing them, while your form is running. Nasty...
Using the code
There are three basic ways that data needs to be transferred: this tip covers when the Child wants to change data on a different Child. This is a more complex operation than going from the Child to the Parent, because it involves a third party - the SecondChild form.
The most obvious way to do this is to add a SecondChild Form reference in the Child and set that when the Child is created. It can then access the second Child form directly and do what it has to .
The problem is that this then depends on two forms existing and doing the right things:
- The Parent form must exist (or you don't have two children )
- The Parent must create both forms - and probably in the right order.
- The SecondChild must be of a specific type or the Child will get an error trying to access it.
Instead, combine Child to Parent and Parent to Child, and have the Parent decide what goes where - since it has to know about both forms in order to create them, it makes sense that it should sort out who needs what data.
Using the Parent as an intermediary
As mentioned above, this is basically a Child to Parent, followed by a Parent to Child. First, you create a property in the Child to supply the data, and an Event to say the data is available. The Parent handles the Event, fetches the data and does with it what it wants.
Child Form property
/// <summary>
/// Data to transfer into / out of form
/// </summary>
public string Data
{
get { return tbData.Text; }
set { tbData.Text = value; }
}
Child Form Event/// <summary>
/// Event to indicate new data is available
/// </summary>
public event EventHandler DataAvailable;
/// <summary>
/// Called to signal to subscribers that new data is available
/// </summary>
/// <param name="e"></param>
protected virtual void OnDataAvailable(EventArgs e)
{
EventHandler eh = DataAvailable;
if (eh != null)
{
eh(this, e);
}
}
Then all the Child form has to do is signal the Event to indicate the data is ready. In this case, we will do it when the user presses a button.
/// <summary>
/// Tell the parent the data is ready.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void butTransfer_Click(object sender, EventArgs e)
{
OnDataAvailable(null);
}
The parent form adds the handler when it creates the form instance.
private frmChild child1;
private frmChild child2;
child1 = new frmChild();
child1.DataAvailable += new EventHandler(child_DataAvailable);
child1.Data = "Hello child 1 from the Parent!";
child1.Show();
// Add another child form
child2 = new frmChild();
child2.Data = "Hello child 2 from the Parent!";
child2.Show();
The parent then passes the information across in the event handler
/// <summary>
/// The child has data available - get it.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void child_DataAvailable(object sender, EventArgs e)
{
if (child1 != null && child2 != null)
{
string data = child.Data;
child2.Data = string.Format("From other child : {1}", data);
}
}
This means that the SecondChild
does not have to be the same type as the first - as long as the Parent knows what they both are (and it has to in order to create them both) it can sort it out without changes to either Child form.
History
- 2013-02-18 First version.
- 2013-02-19 Added links to other tips in series
- 2013-04-03 Corrected spelling error in title: "Transfering" should have been "Transferring"
- 2013-04-03 Corrected the same spelling error in the links to companion tips...