• 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

    • Amazon Alexa+ now has more than a million users by Aditya Tiwari Amazon's muscled-up voice assistant, Alexa+, has reached a new milestone. A company spokesperson told The Verge that Alexa+ has now crossed one million users. The e-commerce giant introduced Alexa+ earlier this year as its generative AI offering. Why? It's a new trend, and everyone is doing it. According to the company, Alexa Plus offers more natural and free-flowing conversations than its predecessor. You can speak half-formed thoughts using colloquial expressions, and the AI assistant should be able to understand you and provide an answer. Announcing its capabilities, Amazon previously said that you will be able to start a conversation on your Echo device and continue it on your phone, car, or computer. One million may not be a significant number when comparing it with the number of Alexa-enabled devices out there. Amazon revealed earlier this year that there are over 600 million Alexa devices globally. However, the number of Alexa+ users has increased from 'hundreds of thousands' in the previous month. The user base is not as big as that of other names like Gemini and ChatGPT because Amazon is still offering the generative AI assistant through an Early Access program, available to Prime and non-Prime members who own a compatible Echo device. We can find social media posts from different users who have been invited to try Alexa+. While there have been positive reviews from some, the road isn't buttery smooth for others. One user claimed that the early access Alexa+ has problems accessing some temperature sensors the previous version of Alexa would. "I also really dislike how it confidently will tell me something that is incorrect now instead of just saying it doesn't know like it used to tell me," the user added. The upgraded AI voice assistant will cost $19.99 per month, but is being offered for free to Prime subscribers. Alexa+ started rolling out in the US as part of its early access program. One reason why Amazon is giving Alexa+ a slow rollout is that the new devices and services chief, Panos Panay, wants to eliminate all the problems related to the generative AI assistant. Amazon's spokesperson told the publication that the early access program doesn't include features like brainstorming gift ideas, scheduling your next spa visit, ordering groceries hands-free, and jumping to your favorite scene on Fire TV. The program also doesn't offer the "new browser-based experience at Alexa.com," which would put Amazon's AI assistant in line with ChatGPT and Gemini. These missing features will be added in the coming weeks and months, as per the spokesperson, adding that almost 90% of the features are now a part of early access.
    • MSI's 32-inch 4K QD-OLED gaming monitor gets a big price cut for UK gamers and professionals by Paul Hill If you’re a gamer in the UK and looking for a monitor to upgrade to then check out the MSI MPG 321URX QD-OLED 31.5 Inch 4K UHD Gaming Monitor which you can now pick up for just 75% of its recommended retail price. The RRP of this monitor is £1,199, but thanks to this deal, you can get it for just £898.99 for a limited time (purchase link down below). With its 4K display, 240Hz refresh rate, and 0.03ms GTG, you’ll have the edge over other gamers by avoiding lag. At 31.5-inches, it’s the ideal monitor size if you’re sitting up close to it at a desk, you don’t want it too big at such a short range, but you also want to be able to see all the image details so 31.5-inches is a good balance. What makes QD-OLED stand out? There are loads of terms used to describe displays such as AMOLED, OLED, LED, and it can all get a bit confusing. This monitor adds yet another acronym called QD-OLED, which stands for Quantum Dot OLED. For you as a buyer, this means your new monitor has self-emitting pixels that deliver great black levels. It also features an enhanced sub-pixel arrangement for extra sharpness. The 31.5-inch 4K UHD monitor has a 3,840 x 2,160 pixel resolution making it ideal for playing games, but also watching movies in the best quality. Other important features worth mentioning are the 1.07 billion colors (10-bit) that the monitor can produce, its 99% DCI-P3 support, and DisplayHDR True Black 400 certification. All of these things make the monitor produce more accurate colours, potentially making it a good choice for professionals editing videos and photos too. Obviously, games will look good too. MSI has also packed in a fanless graphene heatsink which should help to increase the durability of the monitor long-term. This could extend the time until you need to buy a new monitor, further justifying its almost £900 price tag. Gaming and productivity features It’s not just the hardware that makes this monitor excel for gaming, it also comes with great software enhancements and connectivity options. On the software side, you get the following features: Smart Crosshair: Projects a customizable crosshair onto the screen to improve hip-fire accuracy and iron sights in first-person shooter games. Optix Scope: Gives you a built-in aim magnifier with multi-stage zooming and shortcut keys to quickly switch magnification levels. AI Vision: This automatically enhances brightness and colour saturation, particularly in dark areas of the screen, making it easier to see enemies hiding in shadows or dark corners. If you have two separate systems you want to connect to the monitor at once, you can do so with this monitor thanks to KVM support. You can view both sources with Picture-in-Picture and Picture-by-Picture modes. The MSI MPG 321URX QD-OLED 31.5 Inch 4K UHD Gaming Monitor also supports next-gen consoles with features like HDMI CEC Profile Sync, HDMI Variable Refresh Rate (VRR), and 4K:4K downscaling. In terms of connectivity and ergonomics, you get DisplayPort 1.4a, 2x HDMI 2.1 (CEC), USB Type-C with 90W power delivery, and a USB hub. The monitor uses a tilt-, swivel- & height-adjustable stand that is VESA compatible. Should you buy this monitor? The MSI MPG 321URX QD-OLED 31.5 Inch 4K UHD Gaming Monitor is definitely a product for serious gamers looking for top-tier visual fidelity and performance or content creators who need accurate colours and high resolution. Even with the significant discount, it’s still at a premium price and definitely not for everyone. If you are in one of the groups mentioned, then you should give serious consideration to buying the MSI MPG 321URX QD-OLED 31.5 Inch 4K UHD Gaming Monitor as it's the lowest price the monitor has been at on Amazon to date. MSI MPG 321URX QD-OLED 31.5 Inch 4K Gaming Monitor: £898.99 (Amazon UK) / RRP £1,199 This Amazon deal is U.K. specific, and not available in other regions unless specified. If you don't like it or want to look at more options, check out the Amazon UK deals page here. Get Prime, Prime Video, Music Unlimited, Audible or Kindle Unlimited, free for the first 30 days As an Amazon Associate we earn from qualifying purchases.
    • So they went from bloody awful, to still bloody awful? Pass...
    • Hmm, I have been setting folder colors in Teams as we got more and more clients, but they never synced to File Explorer on my Surface Pro 7+. So, all this while, thought the feature wasn't available yet. Guess it'll need to be changed via the SharePoint website for it to sync to File Explorer. Thanks for sharing 👍🏼
  • Recent Achievements

    • Enthusiast
      computerdave91111 went up a rank
      Enthusiast
    • Week One Done
      Falisha Manpower earned a badge
      Week One Done
    • One Month Later
      elsa777 earned a badge
      One Month Later
    • Week One Done
      elsa777 earned a badge
      Week One Done
    • First Post
      K Dorman earned a badge
      First Post
  • Popular Contributors

    1. 1
      +primortal
      533
    2. 2
      ATLien_0
      272
    3. 3
      +FloatingFatMan
      201
    4. 4
      +Edouard
      200
    5. 5
      snowy owl
      138
  • Tell a friend

    Love Neowin? Tell a friend!