One of the first obstacles that people new to C# (or VB.NET for that matter) run into is how to get two forms to communicate with one another. How do you get your main form (a parent) to open and pass along data to another form (the child)? This question typically arises when the programmer wants to create a dialog situation where they click a button to launch a dialog form, ask for some settings and close it to return to the main form they were working on. So I wanted to take a minute to talk about the ways you can do that and show you some code to implement one of those ways. Kick back and lets get ready to hack some code on this episode of the Programming Underground!
The first thing you have to realize when working with the .NET framework is that everything is a class. Forms are no exception. Each form represents a class where you can not only write events to respond to form controls, you can add additional code such as class variables, properties and methods. This gives you, the programmer, the ability to add additional functionality to forms. When you go onto a programming web board asking about passing data between forms you typically get something along the lines of “create a property or method and call it from another form”. This is dandy, but what exactly is meant by that?
As I already have mentioned, forms are classes and that means you can add methods or properties to them. Make these items public and then other classes will be able to see them. This means by adding a public property or method to one form, other forms can use those properties/methods to communicate with it. The great thing about this is that you can also control the “interface” of a form and validate the info coming in and what the form is sending back out.
Using properties (the method I will show you in a second) or class methods are a great way to communicate to other forms about the controls that the form contains. If I want the text value of a textbox on the second form, my first form can call the second form’s property or method and ask for it. The second form in return can decide what to give back to the first form.
In our example below I have two forms. One is named frmMain and is the parent form. This form will contain a simple label, textbox and a button to call the second form we call frmChild. frmChild has a label, a textbox and a button to close the form and return a dialog result. Below is a screenshot of the two forms…
Then we fill out the textbox on the child form and click ok…
… After clicking the OK button we will then see the text appear back in the parent form.
To see how this works we will start with the child form code first to implement a property we will call “ChildText”. We will then use that property from the frmChild form to communicate with the Child Form’s textbox. So let’s take a look at the child forms code…
// Child Form class definition public partial class frmChild : Form { public frmChild() { InitializeComponent(); } // Custom property we are adding to the child form // Notice it is public and communicates with the txtChildText control on this form. public String ChildText { get { return txtChildText.Text; } set { txtChildText.Text = value; } } // Simply ok button to return an OK result back to parent (since this was called with ShowDialog and expects a result) private void btnChildOK_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.OK; } }
In the code above you will notice that we have put in a custom property we call ChildText. Also notice that is public so that our other forms will see it. When we create an instance of this form, besides having all the properties and methods of a typical form, it will also have this property we can use. This property is interacting with the txtChildText textbox control on the form which no other form can see (it belongs to the frmChild after all). Lastly we have a simply OK button click event to tell the parent form that we are returning a dialog result of “OK”.
Now for the parent where we will use the child form. We will create the child form instance, use its ChildText property to give it some data (that it in turn uses to set txtChildText) and then launch the form as a dialog. We can then type something in the box on the child form and click OK to return to the parent form. The parent form can then use the same property (ChildText) to read the data back from the child and set its own textbox.
// Parent form class definition public partial class frmMain : Form { public frmMain() { InitializeComponent(); } // Open child form button private void btnOpenChild_Click(object sender, EventArgs e) { // Create the child form instance, use its new custom property to send it some data. frmChild child = new frmChild(); child.ChildText = "Text Sent From Parent"; // Now show it as a dialog. If the dialog is returning ok, use the property to read back data // and set the txtFormChild control on frmMain with the data typed into txtChildText on frmChild. if (child.ShowDialog() == DialogResult.OK) { txtFromChild.Text = child.ChildText; } } }
As you can see from the code we simply create a new instance of our child form, use the text property we created to send it some data, show the child form with ShowDialog() and everything was returning OK, use the property to set the textbox on the frmMain form.
This method can also be applied to methods of the child form. Declare a method on the child form, make it public so that it can be seen and pass along parameters to help configure the child form before being shown or communicate with after it has been instantiated. I find a property a bit easier since it is essentially two methods in one. One to send data and another to read it back wrapped up in a nice clean name. But you can certainly do either. You can also put the properties/methods back on the parent as well so that your child can ask the parent for data too.
A third method you may hear is to make the controls of the child form public themselves and communicate with them directly. I strongly recommend against this because it opens the form controls up to being corrupted unintentionally. This is basically the same thing as creating a global variable (which most programmers know is bad programming style if you can help it). It also doesn’t provide you the same level of control of what data comes in and out of the form. Just like it doesn’t provide you the same level of control by making private class members public.
By exposing controls through the form’s interface using properties and methods, we can validate, regulate and control how the form communicates and thus keep it free from rogue program elements from messing with the form’s data without warning.
Now you don’t have to use this method for each and every single control. You can make a more generic method or property that make take complex data types and sets multiple controls on the child form at once. By making the property/method generic enough you can use it to set virtually any control on the form. Think about what you can do with this by also putting these properties/methods into an abstract form class and inheriting all your forms from it. Just an idea for you.
I hope you have found this little tip some use and help you create forms that communicate between one another. The theories and code here can be applied to VB.NET as well (with some subtle syntax changes of course). Since both languages treat forms as classes, you can easily add the properties/methods to them for general form to form communication.
Thanks for reading! 🙂