I've got an interesting solution for you, involving closure. In the constructor for Form2, require an Action<TypeOfThing>
object, and whenever you need to return the data to Form1, call that Action and pass the data into it. For example:
class Form1 : Form
{
private void SomeFunction()
{
TypeOfData data;
Form2 form2 = new Form2((d) => { data = d; });
form2.ShowDialog() // or whatever you do with form2
// After you've definitely got your data object from Form2
DoStuff(data);
}
}
class Form2 : Form
{
private Action<TypeOfData> returnData;
private TypeOfData data;
public Form2(Action<TypeOfData> r)
{
returnData = r;
}
private void SomeFunction()
{
// Whenever it comes time to return the data you've collected
returnData(data);
}
}
I've used this implementation in the following circumstance: I had to request a password from the user, and I wanted to do so with a dialog box, so I designed my dialog box with a textbox where the user could type their password, and OK and Cancel buttons. On FormClosing, I'd return the string (their password) by calling the Action, and I would only ever use that Form as a dialog, so I could be sure the variable would be assigned to a string by the time the code continued in Form1. This way I didn't have to make a property for Password, which wouldn't have made sense because the password was only a temporarily necessary piece of data.