• 0

[C#] Return a value from a Form


Question

Ive got a form (we'll call it Form1), which has a button that opens up another little input form (Form2). Form2 contains 4 inputs, i want to return those from Form2 back to Form1.

How do i do that? Ive tried creating an overloaded ShowDialog() method with a return value, but that caused a System.StackOverflowException in mscorlib - always nice.

Am i complicating something simple? Because it feels like i am...

So, how do i return a value from the form?

Link to comment
https://www.neowin.net/forum/topic/347559-c-return-a-value-from-a-form/
Share on other sites

19 answers to this question

Recommended Posts

  • 0

An easy solution is to just create accessors for your input values in form 2. I believe the default implementation of ShowDialog() waits until the form that was opened is hidden or closed to return, so you could do something like this:

Form2 a = new Form2();

a.ShowDialog(whatever parameters there may be);

string value1 = a.value1;

I haven't dealt with this stuff for a while, so i could be completely off, but i think that will work.

  • 0

Say you have an integer called number in Form2. Do this to get it back to Form1:

in Form2 write:

public int GetNumber()
{
return number;
}

in Form 1 write:

Form2 form2 = new Form2()
int myNumber = form2.GetNumber();

Now the myNumber integer which is in Form1 will have the value of number which is in Form2. Hope that's what you need.

  • 0

Make the textboxes public - then you can do the following:

myform f1 = new myform();

DialogResult dr = f1.ShowDialog();

// the user then happily enters data

if(dr == DialogResult.OK) //or whatever it is

{

String mystring1 = f1.TextBox1.Text;

// etc etc...

}

  • 0

No, the form is not destroy after the ShowDialog() exits.

You can very simply add some properties to form2, like this:

public string Input1Value
{
  get
   { return txtInput1.Text;}
}
...

And call them from Form1 after the ShowDialog line.

It's not recommended to make the textboxes public.

  • 0

Ah ok... yep got it working, thanks for the help everyone.

I create the form by doing Form2.showDialog() and there is a close button on Form2 that onClick executes this.Close(). I assumed this meant the form was destroyed once the showDialog() line has passed. But even after close() and showDialog() the form's properties are still accesible.

Since the form is not destroyed when i thought it would be, when does it get destroyed??? When the application closes???

  • 0

If you want to do things a bit more deterministically, and close the form, you can do a couple of things.

1. you can overload your Form2 constructor to take a delegate to call when you have pressed OK on Form2 that passes state info back into Form1.

2. you can create an event in Form2 that Form1 can listen for to retrieve state info.

Realistically, you shouldn't try to access form2's properties after it has closed. You could effectively bring a disposed object back to life(zombie code!) and generate a memory leak.

Either of these options allows you to not worry about whether or not the form was cancelled, and let's you not worry about if properties on Form2 are null or disposed.

From MSDN:

  Quote
When a form is closed, all resources created within the object are closed and the form is disposed.

  • 0
  weenur said:
If you want to do things a bit more deterministically, and close the form, you can do a couple of things.

1. you can overload your Form2 constructor to take a delegate to call when you have pressed OK on Form2 that passes state info back into Form1.

2. you can create an event in Form2 that Form1 can listen for to retrieve state info.

Realistically, you shouldn't try to access form2's properties after it has closed. You could effectively bring a disposed object back to life(zombie code!) and generate a memory leak.

Either of these options allows you to not worry about whether or not the form was cancelled, and let's you not worry about if properties on Form2 are null or disposed.

From MSDN:

586257021[/snapback]

Why not hide the form, grab result properties, and then dispose it?

int result;
frm.Hide();
result = frm.uiresult;
frm.Dispose();

  • 0

You're creating a binding between form 1 and form 2 that's not needed.

// beware: pseudo-code

class Form2
{
 protected:
    Integer val1; // or some other wrapper-type that can be passed as a reference
    Integer val2;
    Integer val3;
    Integer val4;

public:

   // c`tor
   Form2(Integer value1, Integer value2, Integer value3, Integer value4)
   {
         assert(value1 != null);
         assert(value2 != null); 
         // ...

         val1 = value1;
         val2 = value2;
         // ....

       textBox1.SetText( val1.ToString() );
       textBox2.SetText( valu2.ToString() );
       // ...
   }

   void OnClose(...)
   {
      val1.setValue ( textBox1.GetText().ParseInt() );
      val2.setValue ( textBox2.GetText().ParseInt() ); 
      // etc...
   }
}


class Form1
{
public:
    void invokeForm2()
    {
        Integer val1 = new Integer(defaultValue1);
        Integer val2 = new Integer(defaultValue2);
        // etc...

       Form2 form2 = new Form2(val1, val2, val3, val4);
       form2.ShowModal();
       
       // values are assigned now
       MessageBox(NULL, val1.ToString(), NULL, NULL);
    }
}

Weenur's solution is elegant, especially if you want to react immediately when a value is updated.

  Quote
i recommand not calling this.Close()

try this code instead:

this.DialogResult = DialogResult.OK // or .Cancel

this.Opacity = 0

This is just plain stupid. Let's blow up the desktopheap with layered windows that have an opacity of 0!

  Quote
Why not hide the form, grab result properties, and then dispose it?

a) You're creating unneeded bindings between two forms.

b) you can't hide form2 if form1 is in a modal dialog loop.

c) You don't know for sure if the form is destroyed if the call to Show() returns. What if I press ALT+F4, which will close/destroy the window and its childs?

  • 0

actually, Ave, Close()'ing a form doesn't actually dispose it. you can wait for the ShowDialog() to finish and use the results. i find this approach more modular.

using(Form2 form=new Form2())
{
     if(form.ShowDialog()==DialogResult.OK)
    {
        // access own created properties on (form) Form2
    }
}

that's pretty nice. it'll open Form2, show it, when it's done, get the variables and Dispose() it when the "using" block is done.

  • 0

One issue is that you don't know when Dispose is being called or when Form2's finalizer is called. Yes, the "Hide(), access properties, close" solution would work. It does create tight coupling between your forms. That is a property you want to try to avoid. It stifles reuse. Yeah, I know that it maybe a canned solution, so reuse isn't an issue. It is still something to strive for, and the less coupling you have, the better.

  • 0
  weenur said:
From MSDN:

When a form is closed, all resources created within the object are closed and the form is disposed.

586257021[/snapback]

So attempting to access the form's properties after its .close() has been called is very dodgy then!

Ok lots of ideas here... ill try it one of those ways... thanks.

  • 0
  On 24/07/2005 at 19:45, AndreasV said:

You're creating a binding between form 1 and form 2 that's not needed.

// beware: pseudo-code

class Form2
{
 protected:
    Integer val1; // or some other wrapper-type that can be passed as a reference
    Integer val2;
    Integer val3;
    Integer val4;

public:

   // c`tor
   Form2(Integer value1, Integer value2, Integer value3, Integer value4)
   {
         assert(value1 != null);
         assert(value2 != null); 
         // ...

         val1 = value1;
         val2 = value2;
         // ....

       textBox1.SetText( val1.ToString() );
       textBox2.SetText( valu2.ToString() );
       // ...
   }

   void OnClose(...)
   {
      val1.setValue ( textBox1.GetText().ParseInt() );
      val2.setValue ( textBox2.GetText().ParseInt() ); 
      // etc...
   }
}


class Form1
{
public:
    void invokeForm2()
    {
        Integer val1 = new Integer(defaultValue1);
        Integer val2 = new Integer(defaultValue2);
        // etc...

       Form2 form2 = new Form2(val1, val2, val3, val4);
       form2.ShowModal();

       // values are assigned now
       MessageBox(NULL, val1.ToString(), NULL, NULL);
    }
}

Weenur's solution is elegant, especially if you want to react immediately when a value is updated.

This is just plain stupid. Let's blow up the desktopheap with layered windows that have an opacity of 0!

a) You're creating unneeded bindings between two forms.

b) you can't hide form2 if form1 is in a modal dialog loop.

c) You don't know for sure if the form is destroyed if the call to Show() returns. What if I press ALT+F4, which will close/destroy the window and its childs?

Hi, the pseudo-code is exactly what I'm looking for.

Only difference it's I'm with strings instead of int, but that shouldn't matter I believe.

I tried to implement it, but the value of the form1 is unchanged when I return after form2 is closed.

Do you see what I'm doing wrong? Thank you.

    public partial class ChoicesEnumForm : Form
    {
        String choiceSelected;
        Int32 val1;

        public ChoicesEnumForm(string[] choicesText, string choicesFormTitle, String choiceSelected, Int32 value1)
        {
            InitializeComponent();

            choiceSelected = this.choiceSelected;
            val1 = value1;
...
           //Create buttons and link the click event.
         }

        private void choiceButtonClick(Object sender, EventArgs ea)
        {                       
            choiceSelected = ((RibbonStyle.RibbonMenuButton2)sender).Text;
            val1 = 8;
            this.Close();
        }
}

public class MainForm : System.Windows.Forms.Form
    {
        void invokeForm1()
        {
            string[] textos = { "111", "222", "333", "444"};
            char[] choiceCharArr = new char[128];
            Int32 value1 = new Int32();

            String choice = new String(choiceCharArr);
            ChoicesEnumForm form = new ChoicesEnumForm(textos, "text", choice, value1);

            form.ShowDialog(this);

            // Values should be selection on 'form' (choice and value1)
            // But when I put breakpoint here, the value has not changed.

        }
    }

  • 0

I was able to make it work by creating a custom string class.

    public class CustomString
    {
        string X;

        public CustomString(string X)
        {
            this.X = X;
        }

        public void SetValue(string value)
        {
            X = value;
        }

        public string GetValue()
        {
            return X;
        }
    }

    public partial class ChoicesEnumForm : Form
    {
        CustomString choiceClicked = new CustomString("");

        public ChoicesEnumForm(string[] choicesText, string choicesFormTitle, ref CustomString choiceSelected)
        {
            InitializeComponent();

            this.Text = choicesFormTitle;

            choiceSelected = choiceClicked;
            ...
            //create buttons and link event to it
            button[x].Click += new EventHandler(choiceButtonClick);
         }

        private void choiceButtonClick(Object sender, EventArgs ea)
        {                       
            string valueSelected = ((Button)sender).Text;
            choiceClicked.SetValue(valueSelected);
            this.Close();
        }


//Parent form
        public void invokeForm()
        {    
            CustomString revSelected = new CustomString("");
            ChoicesEnumForm form = new ChoicesEnumForm(revisionChoices, "Choose revision of product " + GetProductNameSelected(), ref revSelected);

            form.ShowDialog(this);

            string revSelectedString = revSelected.GetValue();
        }

  • 0

Glad you solved it, but just so you know, the reason it worked once you made a custom class is because a string is a struct, not a class. Strings (structs) are passed by value instead of by reference. You could have passed the strings with the ref keyword instead of making a custom class.

  • 0

Here's another simple idea. Try adding a setForm1(Form1 form1) method into Form2. After creating (but before calling showDialog()) Form2, you could pass in a reference to form1. When the value has been set in Form2 (I'm not sure what way you're validating your data in the second form but I'm not sure there's an action listener), set a value in form1 (which you've now stored a reference to locally in Form2), e.g. form1.value = this.value; That way, the value gets passed to where you need it while Form2 is still open. This might not be the best way to preserve the OOP coding of the forms but it should work perfectly fine.

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • Microsoft updates Media Creation Tool with a newer Windows 11 release by Taras Buria If you want to download a Windows 11 image or create an install media, the Media Creation Tool app is one of the best options—simple, fast, and, more importantly, official. While there are other useful alternatives, such as Rufus, Media Creation Tool remains the default choice for those who simply want a clean Windows 11 installation on a supported computer. Thanks to the latest MCT update, you will have to deal with fewer updates after installing Windows 11. Microsoft has quietly updated the Media Creation Tool app so that it downloads the latest Windows 11 release, version 24H2, with build number 26100.4349. This is the most recent public Windows 11 update (June 2025 Patch Tuesday), which eliminates the need to download large updates for your PC after installing the operating system. You can download Media Creation Tool from the official Windows 11 website. If you are familiar with it, this simple app can generate a Windows 11 image with the language you need or create a bootable USB media. Note that it only works on Windows, so Linux or macOS users have to download Windows images directly from the official website and then use apps that are available on their platforms. Another thing worth noting is Media Creation Tool is not the right choice if you want to install Windows 11 on an unsupported PC. In such a case, you can use MCT to download an ISO and then create a modified install media with apps like Rufus or Ventoy as described in our dedicated guide. If you want a more exotic Windows 11 Edition, try the Oofhours Media Tool, which allows you to select Windows 10 or 11, architecture (x64, x86, or ARM64), language, and edition. In addition to standard Home and Pro, the application can download non-mainstream SKUs, such as Enterprise, Education, or Professional for Workstations. Via: Deskmodder
    • Putting premium on your higher end laptops really makes it feel like your lower end laptops are worse.
    • Funny enough just removed insta account and whatsapp is next. Less power needed now
    • If you only show the stop code and what failed for less than 2 seconds, what use is it?
    • How about using all that hot air Zuck spews? That surely can power something...
  • Recent Achievements

    • Conversation Starter
      Kavin25 earned a badge
      Conversation Starter
    • One Month Later
      Leonard grant earned a badge
      One Month Later
    • Week One Done
      pcdoctorsnet earned a badge
      Week One Done
    • Rising Star
      Phillip0web went up a rank
      Rising Star
    • One Month Later
      Epaminombas earned a badge
      One Month Later
  • Popular Contributors

    1. 1
      +primortal
      538
    2. 2
      ATLien_0
      207
    3. 3
      +FloatingFatMan
      174
    4. 4
      Michael Scrip
      148
    5. 5
      snowy owl
      119
  • Tell a friend

    Love Neowin? Tell a friend!