• 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

    • How to change folder colors in OneDrive by Taras Buria Microsoft's OneDrive cloud storage has plenty of useful productivity features that help you get around your file libraries. Colored folders are a relatively new feature that not every OneDrive user is aware of. While the ability to have colorful folders might seem minor at first glance, it can be very helpful for sorting stuff in your OneDrive. Microsoft says the feature lets users "personalize and manage folder colors for better content visibility." Even Apple agrees with this—iOS, iPadOS, and macOS 26 let you change folder colors in the Files/Finder app. Change folder color in OneDrive on Windows The process is very simple, but it is not the same as changing a folder icon in File Explorer. While you can change the icon of any folder in OneDrive on Windows 11 (Right Click > Properties > Customize > Change Icon), these icons do not sync across platforms. At the same time, while OneDrive folder colors do sync, the feature is not available for personal accounts in the web version of OneDrive. As for mobile devices, it is coming soon to Android and iOS OneDrive clients. Despite the current limitations, here is how to change folder colors in OneDrive on Windows: Make sure OneDrive is set up and running and sync is not paused. Find the folder whose color you want to change, and right-click it. Select OneDrive > Folder Color. Pick one of the 16 colors available and click Ok. The OneDrive app will sync your changes so that they appear across all devices that support folder colors in OneDrive. If you have a business account, you can open OneDrive for the web, right-click any folder and select Folder Color. Changes will sync across your devices right away. Do you find colored folders in OneDrive useful? Share your thoughts in the comments.
    • Awesome. That's what I was thinking Jim. Yea from what I can tell you connect the AIC card to the AIC header on the motherboard, so it doesn't just run through the PCI lanes. That's fine guys. Thanks for clarifying 🙂 I was getting a little bit lost with all of this, but I need a minimum of TB3 and the connector on the MB has it, but not on the back of my PC chassis / MB IO shield. Anyway I found that the cheapest I can get it is Amazon at 70 quid, so I'm just gonna have to fork out for it. Thanks everyone. 🙂 👍  Don't worry about Mindovermaster. He's just his chirpy cheerful self lol. Thanks everyone 🙂
    • I wonder why you say that. As we speak, I'm using it to slash off several minutes of my life.
    • I think you may need to adjust your style of approach. I know you won't though. While some were affected by performance issues, and it's not a huge gap... you're acting as if Ryzen couldn't handle 11 at all. Performance issues are purely based on some facts in certain scenarios, while others are not. I see one link with a handful of people discussing the topic. I didn't join those topics or seek them out myself, as I didn't encounter noticeable drops in performance going from 10 to 11. When 10 came out, during that beta testing phase... I was able to continually crash my system simply by renaming files. It might also have to be because I don't have my nose stuck up the butt of single digit percentage points. I don't benchmark my PC every time something new comes out. Single percentage point differences in performance only ruffle the feathers of those that don't care about daily use. If you have a race car, do you compare that to your daily driver? Do you expect your Honda Accord to break the 9 second quarter mile like your 1000HP Pontiac Firebird? If you're so worried about FPS instead of enjoying your games... perhaps opening a curtain in your basement might provide a new perspective in life.
    • Currently updating my Win10 IoT Enterprise LTSC 2021 in a VM (QEMU/KVM) on Linux. but damn, updates take forever (makes me appreciate the lightness on Linux all the more). to give you a general idea... this update finished at 37 minutes into system uptime and I would estimate updates have been running roughly 20-30 minutes (some of this would be download time, but even subtracting that I would guess that 20-30min is close). granted, I only got two cores of my four core CPU (i5-3550) dedicated to the VM. but still, Linux wipes the floor with Windows in this regard. plus, that does not count the reboot which takes even more time.
  • Recent Achievements

    • Reacting Well
      rshit earned a badge
      Reacting Well
    • Reacting Well
      Alan- earned a badge
      Reacting Well
    • Week One Done
      IAMFLUXX earned a badge
      Week One Done
    • One Month Later
      Æhund earned a badge
      One Month Later
    • One Month Later
      CoolRaoul earned a badge
      One Month Later
  • Popular Contributors

    1. 1
      +primortal
      535
    2. 2
      ATLien_0
      269
    3. 3
      +FloatingFatMan
      211
    4. 4
      +Edouard
      204
    5. 5
      snowy owl
      140
  • Tell a friend

    Love Neowin? Tell a friend!