• 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

    • Size 15. In the first week I managed to get a full week before having to recharge from 10%. I looked online and Samsung recommends recharging it when it gets to 20-30% to preserve the battery life. In the second week, started wearing my Galaxy Watch6 Classic again, because I read that it offsets sensors to the Watch, meaning the battery lasts even longer... and a week on (today) the ring was at 31% when I recharged it fully again, so a difference of over 20% in combination with the Watch. By the way I do not wear my Watch to bed, so it is only the Ring doing the sleep tracking (which is hit or miss tbh) it stops tracking for an hour or two in the night, which is really annoying. I had the same thing with the Watch, and I found it uncomfortable to have on in bed. I have been reading that the battery can start to go bad even after the first week so I am glad it isn't affecting me (yet).
    • Visual Studio gets even smarter with more AI models and billing updates by Usama Jawad Visual Studio and Visual Studio Code are among the most popular integrated development environments (IDEs) out there. The tools boast more than 50 million monthly active users, which isn't surprising considering their platform agnosticism, deep integration with the Microsoft ecosystem, and the power of GitHub Copilot. Now, Microsoft is looking to entice even more customers who are eager to use AI models to boost their productivity during the development process. In a blog post, Microsoft has stated that it has updated the AI models list available in Visual Studio to default to smarter options. For example, Copilot will now use GPT-4.1 rather than GPT-4o, since it offers better responses with faster performance. In addition, users can now select between the following models to enhance their coding experience based on their preferences: Claude Sonnet 4 Claude Opus 4 Claude Sonnet 3.5 Claude 3.7 (non-thinking and thinking) OpenAI o3 mini Gemini 2.0 Flash Gemini 2.5 Pro Microsoft has noted that your selected model will persist across your workflows, so if you're unsure about which model to leverage, you can refer to its documentation here. Furthermore, Visual Studio is making it easier to switch between models that are included in your plan through a prompt in the model selector. When it comes to billing updates, Microsoft has built a new Copilot Consumptions user experience that can be accessed by navigating to the Copilot badge present in the top-right corner of the IDE. As the name suggests, this panel shows your consumption in an easily digestible format. You can also click on Manage Plan, which will take you to the GitHub website. It is important to note that some models are request-heavy, and Visual Studio will now indicate this to you while you are selecting your model. If you exhaust your premium requests, you will shift to a standard model seamlessly. You should also keep in mind that the GitHub Copilot pricing plans have been updated, and the billing experience in Visual Studio does reflect them.
    • Indeed. It's apparently just a new search window that calls itself a "launcher"...yeehaw?! bleh.
    • Last I checked, their "support clock" runs for five years. So EOL at end of 2028 for this model? Roll your own looks better all the time. I do understand that's not for everyone. I think the least they could do is offer you six months of free cloud so you could migrate to new hardware when the time comes. Assuming you stick with them as your hardware vendor, of course.
    • Music Collection 3.9.1.1 by Razvan Serea Music Collection is a free tool to archive and manage your music library. Add CDs, LPs, tapes, or digital files manually or via the Internet. Retrieve album data by artist, title, barcode, catalog number, or CD scan. Auto-import metadata from audio files. Browse, sort, filter, export, import, and generate reports effortlessly. Music Collection features: The program creates the collection's database in a Microsoft Access format, so if you want later, you can use it, without the help of the program. The user can create as many as different collections wants. Accepts all kinds of musical media (cd, lp, dvd-a, audio files etc.). Specially customized to add and edit classical music albums. Retrieves data from the Internet, such as cd info, album cover, artist information, tracks, and the lyrics of each track etc. For every album the program saves all media contained, every medium tracks and the lyrics for every track. Displays albums using filters or the advanced search feature. Lists selected albums in a grid or using images (default setting). Presents all items contained in the album, in one page for an easy album overview. The details that are shown there are: album cover, album artists, notes, the tracks of each medium, the lyrics of each track and the duration of each one, as well as the total duration of the album. Exports album information to html file. Exports collection albums to html,txt,csv,excel files. Imports album information from text files exported by another program. Manages all program data, such as a list of singers, composers, etc. Manages artist information (biography, best albums). Prints all the data shown in each table.. Creates reports, which you can configure by your preference.. Manages album loans. Shows collection statistics. Searches for tracks and opens the album medium that contains them. Skinable. The user can select from 30 different skins. Multi-language support. Music Collection 3.9.1.1 changelog: Added: Show selected group item total duration. Added: Option to show only the checked albums. Added: Save the checked album property. Added: Play checked tracks. Fixed: Some minor bugs. Download: Music Collection 3.9.1.1 | 8.0 MB (Freeware) Download: Portable Music Collection 3.9.1.1 View: Music Collection Home page | Screenshot Get alerted to all of our Software updates on Twitter at @NeowinSoftware
  • 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
      528
    2. 2
      ATLien_0
      207
    3. 3
      +FloatingFatMan
      168
    4. 4
      Michael Scrip
      150
    5. 5
      snowy owl
      124
  • Tell a friend

    Love Neowin? Tell a friend!