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.

Note that this info is not limited only to forms. It can be used on any kind of class. Forms are the ones most frequently asked about, so the tutorial is written from that perspective, but otherwise, the info in the Modeless section works for any kind of classes that need values to be passed around.

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: DefaultForm, FirstNameForm, and LastNameForm. 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. Edit: that used to be a good example before the Find dialog got changed in later versions of Visual Studio. A better example now would be the Find dialog in Notepad.

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 FirstNameForm 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.

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:

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:

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:

Remember that we added the name to our NameUpdatedEventArgs? That's in the variable e. 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 modal forms. A form is treated as modal 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 LastNameForm 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):

public string LastName
{
get
{
return lastNameTextBox.Text;
}
}

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":

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 new Form1() is really no different than new Random() 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 DisplayNameForm. 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:

public DisplayNameForm()
{
InitializeComponent();
}

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.

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.

Well, I won't pretend it's my idea. It's a design concept that's been out there a long while. The problem is that a lot of programmers come from a procedural model of programming and don't make full use of events. I did; that's why I had to learn this stuff the hard way. Hopefully some people will gain some good habits from this.

Can you expand this to datagridviews on 2 forms named "Expenses" and Bank Account" with both opening a third form named "Calculator"? Double clicking on a cell in the datagridview of either "Expenses" or "Bank Account" opens form 3. Calculations are performed and returned to the appropriate cell in the DGV of the originating form. Doing this with a single DGV form (frmExpenses) is easy as all you have to do is return the calculated result by using a line similar to frmExpenses.datagridview1.Value(cell address row and column)= "the calulated result"

Can you pass the form name (frmExpenses or frmBankAccount) to the calculator form for use in the line that returns the calculated result? This is the bit that I have not solved.

I had a big project all planned out (or so I thought) and then it became evident after making all of the forms that I couldn't pass data between forms. I wasn't sure where to instantiate my forms and classes so that I could control all of them.

Nice tutorial very good.
But I am having a problem. I am using WPF Page based navigation and I am having trouble passing values from one page to another. How can i do this since i just have to navigate to a new Hyperlink to view another page and i need to carry along data from the previous page.

Unfortunately it's not as simple as "just an explanation" for that. It's a concept. I've never used WPF Navigation applications before, so I won't be as good at explaining it as the first link. I suggest trying it again.

Very very concise, detailed, and overall helpful post, Thanks alot! There are a few typos however, I think we can let you slide. The blogsphere needs more post with great structure and organization like this one!