473,395 Members | 2,079 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes and contribute your articles to a community of 473,395 developers and data experts.

How to get data from Form1 to Form2 (or any other forms).

Curtis Rutland
3,256 Expert 2GB
This question is asked practically every day in the C# Forum: "how do I get a value from Form1 to Form2?" or the other way around. There is a shocking amount of bad advice out there on the internet about how to go about doing this. This tutorial is intended to show you more "correct" ways of passing data between forms.

The scope of this tutorial is limited to passing data between forms. We will look at both properties and custom events, but in a brief overview. There are already some excellent tutorials that cover some of these topics in more detail, should you want more information:
Quick and easy custom events
Bulding an application - Part 1
Building an application - Part 2

Let's start with a new Windows Forms project (though note, these methods can also be used for WPF forms as well). I'm creating three forms: [inline]DefaultForm[/inline], [inline]FirstNameForm[/inline], and [inline]LastNameForm[/inline]. DefaultForm is "Form1", the Form that is opened when the application starts.

There are two types of child form: modal and modeless (non-modal). There are different techniques for getting information from both, since they behave differently.

Modeless child windows do not require an immediate response, and do not block you from focusing the parent form again. You are allowed to freely switch back and forth between them. An example of a modeless dialog would be the "Find" (ctrl+F) dialog in Visual Studio.

Modal dialogs, on the other hand, block you from switching back to the parent window. They require a response before continuing. An example of a modal dialog is a MessageBox.

Depending on which type of form you choose to use, you will need to get the data from it differently.

Modeless

First, we'll visit modeless forms. A form is treated as modeless when it is opened by the .Show method. Execution does not stop on that line; the code after it continues to execute even though the child form is now shown and focused.

We'll use [inline]FirstNameForm[/inline] as the modeless dialog.

Since execution does not stop, we need a way to know when the value we want is updated. Custom events are the answer. The reason we like to use events rather than just passing properties around is that we don't want to tightly couple our forms. DefaultForm doesn't need to know anything more about FirstNameForm than it should. This way, it doesn't have to know anything about it other than that it has one event. It doesn't need to know names of properties, and it doesn't have to guess about when the properties are updated.

Another benefit is reusability. You may want several forms to update themselves when a child window does. This way, each form can subscribe to the event and handle it the way they choose. As another expert on this forum explains, it's like bingo. When a number is drawn, the guy doesn't go down the aisle and mark each person's board. He calls it out (an event) and each person handles it accordingly (the subscribers handling the event).

Let's create a custom EventArgs class to suit our needs. This simple class extends EventArgs, and has a public string property called Name.
Expand|Select|Wrap|Line Numbers
  1. public class NameUpdatedEventArgs : EventArgs
  2. {
  3.     public string Name { get; set; }
  4. }
We'll use that EventArgs class to pass our value with. Now, we must create the event itself. Inside the class definition for FirstNameForm, we'll add the folowing code:
Expand|Select|Wrap|Line Numbers
  1. public event EventHandler<NameUpdatedEventArgs> FirstNameUpdated;
  2.  
  3. protected virtual void OnFirstNameUpdated(NameUpdatedEventArgs e)
  4. {
  5.     if (FirstNameUpdated != null)
  6.         FirstNameUpdated(this, e);
  7. }
The first line creates the event itself. The method that follows actually triggers the event itself. It expects you to pass it a NameUpdatedEventArgs, which it will use as one of the event's parameters. So when we want our FirstNameUpdated event to be triggered, we call our OnFirstNameUpdated method.

Now that we have the code for an event up, we need to add the logic to call that event. In my example, we're going to update the value when the user clicks a button:
Expand|Select|Wrap|Line Numbers
  1. private void UpdateButton_Click(object sender, EventArgs e)
  2. {
  3.     string newFirstName = firstNameTextBox.Text;
  4.     NameUpdatedEventArgs nuea = new NameUpdatedEventArgs();
  5.     nuea.Name = newFirstName;
  6.     OnFirstNameUpdated(nuea);
  7. }
First, we're getting the new first name. Then, we create a new NameUpdateEventArgs object. Then, we assign the new first name to the Name property of the args. Lastly, we call the method that triggers the FirstNameUpdated event.

Now we're done with FirstNameForm. It's set up to broadcast its event, and needs nothing else to work.

In the DefaultForm, we need to handle the event. In this example, we are going to open the child window as soon as we open the DefaultForm, so we'll create and show the FirstNameForm in DefaultForm's constructor:
Expand|Select|Wrap|Line Numbers
  1. public DefaultForm()
  2. {
  3.     InitializeComponent();
  4.     FirstNameForm fnf = new FirstNameForm();
  5.     fnf.FirstNameUpdated += new EventHandler<NameUpdatedEventArgs>(fnf_FirstNameUpdated);
  6.     fnf.Show();
  7. }
The first line of the method is the standard method call that Visual Studio adds to every form to set up all the GUI components. The next line creates a new instance of FirstNameForm.
The next line adds an event handler**. And the last shows the window in a modeless way.

**A quick note on adding event handlers: Visual Studio will do most of the work for you. Type the beginning of the line up to the +=:



And Visual Studio asks you to push TAB. Push it:



And it finishes the line for you. But it wants you to push tab again. Do it:



And it creates the handler method for you as well. It really does take the guesswork and memorization out of making event handlers.

That method that VS created for us will be the code that executes every time that FirstNameUpdated is triggered. Let's fill it in:

Expand|Select|Wrap|Line Numbers
  1. void fnf_FirstNameUpdated(object sender, NameUpdatedEventArgs e)
  2. {
  3.     if (e != null && e.Name != null)
  4.         firstNameLabel.Text = e.Name;
  5. }
Remember that we added the name to our NameUpdatedEventArgs? That's in the variable [inline]e[/inline]. First we check to make sure e and it's property are not null, then we take the Name value from e and assign it to a label.

And that's that. When we run the program, we see this before the update:



And after update:



The FirstNameDialog will not go away until you close it.

Modal

Next, we'll visit modeless forms. A form is treated as moda; when it is opened by the .ShowDialog method. Execution does stop at that line until the child form is closed. The ShowDialog method returns a DialogResult object.

We'll use [inline]LastNameForm[/inline] as the modal dialog.

Now, modal dialogs are a bit different of a model from the other types. They're usually more limited in their focus and purpose, and execution of the parent form is blocked while they're open,\ so it's OK to tightly couple them with a parent form. To an extent. Neither form should know about the UI controls on the other, of course. That's some of the worst advice that's common on the web "make your TextBox public." Don't do that!. Instead, wrap your TextBox's Text property in a public Property. Here's how we would do this in LastNameForm (this would be added inside the class LastNameForm):

Expand|Select|Wrap|Line Numbers
  1. public string LastName
  2. {
  3.     get
  4.     {
  5.         return lastNameTextBox.Text;
  6.     }
  7. }
Now instead of dealing with an entire TextBox, we're just dealing with a string.

Now, since we don't need a way to know when the child form is closed (because ShowDialog is a blocking call), we just need to make sure to close the form when we get what we want. In this example, I'm closing the form when someone clicks a button labeled "OK":

Expand|Select|Wrap|Line Numbers
  1. private void OkButton_Click(object sender, EventArgs e)
  2. {
  3.     this.DialogResult = DialogResult.OK;
  4.     this.Close();
  5. }
We're setting the DialogResult to OK to let the other form know it wasn't forced closed or cancelled.

And that's all we have to do for LastNameDialog. Now we need to look at creating the dialog and retrieving it's value.

In DefaultForm, we'll launch a LastNameDialog when a user clicks a button:

Expand|Select|Wrap|Line Numbers
  1. private void GetLastNameButton_Click(object sender, EventArgs e)
  2. {
  3.     LastNameForm lnf = new LastNameForm();
  4.     DialogResult res = lnf.ShowDialog();
  5.     if (res == DialogResult.OK)
  6.         lastNameLabel.Text = lnf.LastName;
  7. }
The first line creates a new LastNameForm. The next calls it as a Modal dialog, and retrieves its response once it's closed. The next lines test to see if the DialogResult was "OK", and if so, uses the value of the LastName property for a label on the DefaultForm.

And that's really all there is when it comes to modal dialogs. Remember, this way is less involved, but Modal dialogs block execution of the main form, and you can't switch from one to the other. So you must make your choice of which to use wisely.

Here's how it looks when using it. Before clicking OK:



After clicking OK:



Note that the dialog went away when we clicked OK.

Passing a value to a new Form

Another very common related question involves passing values to a new form. One very easy way to do this is to remember that Forms are just Classes, and that all classes have constructors. Calling [inline]new Form1()[/inline] is really no different than [inline]new Random()[/inline] or any other class. And because this form is a class you are creating, you have control over the constructor, and its parameters.

I'll continue on with the previous example. We'll add a form called [inline]DisplayNameForm[/inline]. This form is simply a display form, not an input form, so we don't have to worry about events or anything like that. But we need it to display the name, so it needs both names when it's created. Normally, when a form is created, it's created with a default constructor:

Expand|Select|Wrap|Line Numbers
  1. public DisplayNameForm()
  2. {
  3.     InitializeComponent();
  4. }
But just because it starts that way doesn't mean it has to stay that way. Let's add some parameters to the constructor, and some assignment logic.

Expand|Select|Wrap|Line Numbers
  1. public DisplayNameForm(string firstName, string lastName)
  2. {
  3.     InitializeComponent();
  4.     firstNameLabel.Text = firstName;
  5.     lastNameLabel.Text = lastName;
  6. }
Now the form requires both a first name and a last name to be created. And when it's created, it assigns those values to some labels on the form.

This, of course, changes the way we have to create and call the form. For this example, in DisplayForm, I'm showing this DisplayNameForm on a button click:

Expand|Select|Wrap|Line Numbers
  1. private void DisplayNameButton_Click(object sender, EventArgs e)
  2. {
  3.     string firstName = firstNameLabel.Text;
  4.     string lastName = lastNameLabel.Text;
  5.     DisplayNameForm dnf = new DisplayNameForm(firstName, lastName);
  6.     dnf.Show();
  7. }
The first two lines gather the names. The third is the actual creation of the new form. Notice that we're providing the names as parameters to the constructor. They match the parameters in the constructor's definition. Lastly, we show it like any other form.

Conclusion

I hope you have enjoyed this tutorial. I've tried to make it as simple as possible while still following sound design and object oriented principles.

This article was crossposted from my blog.
Dec 21 '10 #1
0 11110

Sign in to post your reply or Sign up for a free account.

Similar topics

1
by: Andrew Wrigley | last post by:
Hi Should a hidden form become visible when all other forms are closed? This is what happens, and to ensure that it is always hidden, I have to set the on got focus event handler of the form...
1
by: jbroome | last post by:
I have a main form which contains information for several subforms which I can link no problem but i also have some other information from another table which i wish to attach to the main form for...
4
by: Cantekin Guneser | last post by:
i am new to windows aplication, i am planning to desing a program which has login form. i want to use in formation at second form which i used in login form. ex: i filled a dataset in login form...
2
by: Andy | last post by:
I have a form (formA). This form used to following code on FormA to load a new form(FormB). formB f = new formB(); f.ShowDialog(); However: on formB, I am unable to access any object...
1
by: Dan | last post by:
Is it possible to access controls on other forms when using managed C++? In VB, it was a simple matter of declaring the form as global, but this is apperently not possible when using managed code....
3
by: Saket Mundra | last post by:
I have multiple web forms in my application. The user after logging on is directed to form1 where he enters information desired. Once finished he is directed to form2 and the same procedure goes on...
4
by: Robin Tucker | last post by:
How can I make my form stay on top of all the other forms in my application? I don't want the form to stay on top in Windows as a whole, just be on top of all the other forms in the given...
0
by: msxkim | last post by:
I would like to know how to send messages to other form when one form is closed. For example, I have Form1. Form2 is opened from Form 1. When you close Form2, can you access Textbox control on...
2
by: doncee | last post by:
I thought that you could take a value created in a text box of one form & make it available for use by other forms in the same database as until you closed that database. If this is possible...
10
by: =?Utf-8?B?MjJQb20=?= | last post by:
Hi All, Thanks to Family Tree Mike I've managed to get a Solution up and running, now comes the fun part. How do I call forms from other Class Libraries and how do I use a Background form...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.