Passing data between two Forms in WinForms
Passing data between two Forms in WinForms
MENU
Yes, WinForms is an older technology, and no, there's nothing particularly sexy about it. But it works
and it's quick to spin up a new program. Many businesses still have legacy apps built with it, and its
drag-and-drop interface makes it easy to use in a classroom setting too.
True to its name, most things you do in WinForms revolve around Forms, and the creation of multiple
Forms for performing different functions. Functions like collecting data from the user, or displaying a
record from the database for the user to edit. After the user enters the requested data, or makes
changes to that record, and presses your OK button to close the current Form, their changes are lost
unless you do something with them first.
You might want to save the changes to a database at this point, but more often you'll just want to pass
the data back to the original Form that created the one that was just closed.
Note: All the following code in this post is also available on Github.
I see this question asked a lot on Stack Overflow, and it's usually one of these slight variations:
Every program's different, but this particular issue has a few practical, common solutions. Let's mockup
a question first - this is pretty typical of the questions I see:
I have two Forms. The first Form has a button for opening the second Form.
The second Form collects input from the user in some TextBox controls. When they're done
and close it, I need to pass those values back to the first Form.
Here's is my code but it's not working as expected. How do I get what the user entered back
into the first Form?
This is a very basic example. The first Form displays the data collected in the second Form, maybe in
a DataGridView or just some Labels. Or maybe the first Form takes some action on the data from the
second Form, like saving it to a file. Whatever.
Here's what the awesome app referenced in the question might look like:
C#, WinForms
Two Forms, Form1 and Form2
Form1 starts with the program, and contains a DataGridView and a Button for opening Form2
Form2 has a couple TextBox controls for accepting user input, and a button to close the Form and
“Save” the input
A Form is just another class, and in order to change the properties of any class, you need to have a
reference to the particular instance you wish to modify.
Look at the code in the btnSaveInput_Click() event method above. If you're trying to create a new
instance of a Form in order to update it, you're making a fundamental mistake about how class
instantiation works. Multiple instances of a class do not automatically share data between them.
In other words, when you create a second instance of Form1 inside of Form2, it has nothing to do with
the original instance of Form1 that you started out with. This second instance of Form1 will go out of
scope and become inaccessible when the btnSaveInput_Click() method ends, and the values you
set in it will not carry over to the original Form1.
(You might be tempted to define public static fields that are easily accessible from everywhere, but try
to avoid it. The natural progression is then a static class to hold those static fields, and pretty soon you
have a blob often called the god class that's nigh impossible to debug. Been there, seen that.)
You have two practical choices for getting the data back into the first Form (Form1):
First, I'll explain how you could do this, then I'll explain why you shouldn't.
In order to push data back to Form1, you need a reference to it. In general, the easiest way to do that
is to pass a reference in the constructor when you instantiate Form2:
...
Now you can access public properties, methods, whatever on the first Form.
int age;
if (int.TryParse(txtAge.Text, out age))
form1.Age = age;
this.Close();
}
}
The first issue I have with this method is reusability. Imagine that next week, you want to use Form2
from another Form, say Form3. You want to collect the same data but present it in a different manner.
Now your Form isn’t as reusable, because it's not so clear who will be calling the Form.
In general, a thing being called should know little to nothing about the thing calling it.
There is no reason for Form2 to know about the other Forms, user controls, class libraries, etc that
could potentially use it. You should not have a bunch of if/else statements to handle this kind of logic.
Imagine the following, where we have two Forms (an employee Form and a student Form), and an
additional class library with no UI of its own, all using the Details Form to get name and age.
this.Close();
}
}
The DetailForm Form knows way too much about what's potentially calling it, and has to plan for
every possible caller - things get ugly quick. Also, making changes to one of the callers requires
changing the shared Form as well.
A better option is to make the data available from the second Form, then let the individual callers
retrieve the data (or not) as they choose. The easiest way to do this is to create public "getter"
methods on the second Form, which I'll show below.
(If you're unfamiliar with getter/setter properties, check out this thread - it's 10 years old and for Java,
but the reasoning is the same for C# and remains relevant even today.)
Here's a copy/paste of the previous code block, modified so that the shared Form knows nothing about
its callers.
lblStudentName.Text = detailForm.Name;
}
}
}
detailForm.ShowDialog();
EmployeeName = detailForm.Name;
}
}
}
Name = detailForm.Name;
Age = detailForm.Age;
}
}
// Even this could be removed, if you set this button as the Accept
// button on the Form, or set a DialogResult value on the button
private void btnClose_Click(object sender, EventArgs e)
{
this.Close();
}
}
The second Form is left cleaner. It requires no special knowledge of its callers, and has greater
reusability and maintainability. The callers can grab as much or as little data as they need, or do
nothing at all.
You can use this method to retrieve whatever data you need from the child Form (Form2), such as a
List or TextBox values.
More Reading
I hope this helped clarify a few things. If it still seems unclear, or you see a possible error somewhere,
please leave a comment below and we’ll figure it out!
This is a really common question for beginners. You can do a search for "passing between forms
winforms" and you'll get quite a few hits. Here are a few good ones. I haven't read them all through
end-to-end, but they're thorough and will give you something to think about, at least.
Share:
WRITTEN BY
Grant Winney
NEXT
PREVIOUS
I occasionally include affiliate links for products I own and have found to be of good quality, or after checking reviews and
feeling confident they are good products. These links don't increase your cost at all, but using them helps pay for this blog and
the time I put into it. Thanks!
Comments
Sorry, the browser you are using is not currently supported. Disqus actively supports the following
browsers:
Firefox
Chrome
Internet Explorer 11+
Safari
Hope you can provide code for setting combobox's selectedvalue or selecteditem using vb.net. Anyway,
you provide great help. Thanks.
WELCOME!
I write about whatever happens to be on my mind when I sit down. I'm a father of 5, developer by profession, and aspiring
woodworking hobbyist. I enjoy the Pi and other programming projects, as long as there's a purpose. A few more things about
me...
If you like what you read today, and you'd like more of the same, enter your email below to receive weekly updates.
email address
Subscribe
LATEST POSTS
Querying Amazon's product details with the Amazon Product Advertising API
October 12, 2018
How to select an earlier .NET version on Visual Studio for Mac (tl;dr: you can't)
August 20, 2018
BACK TO TOP
© 2018 Grant Winney (via Ghost and Wildbird) · Affiliate Links · Cross-Posting · License