1

I have two Forms: MainForm and OptionsForm, wich has a button (OK) that applies the some changes on MainForm. When I open the OptionsForm for the first time everything is ok, with the default values.

After I make some changes and and click OK the options are applied but when I open the OptionsForm for the second time, I wanted to hold the previous values, not the default ones like its happening.

OptionsForm is opened through MainForm like this

OptionsForm formOptions = new OptionsForm();
if (formOptions.ShowDialog(this) == DialogResult.OK)
{
    // etc..
}

//...

public string otherLabel
    {
        get { return formMainLabel.Text; }
        set { formMainLabel.Text = value; }
    }

In OptionsForm I have a NumericUpDown and want to hold its value

private MainForm mainForm = null;
public OptionsForm(Form callingForm)
{
    mainForm = callingForm as MainForm;
    InitializeComponent();
}
// ...
private void btnOK_Click(object sender, EventArgs e)
{
     this.mainForm.someLabel= someBox.Value.ToString(); // NumericUpDown
     this.mainForm.otherLabel = "abc";       //>>> Getting NullReferenceException
     this.Close();
}

Now I can hold my settings but I'm getting a NullReferenceException. I tryed this but it's still not working. Any sugestion?

Community
  • 1
  • 1
mafap
  • 371
  • 3
  • 18
  • 40
  • how did you open the optionform ? – matzone Sep 04 '13 at 17:46
  • @mafap Please show us what you've tried. – devavx Sep 04 '13 at 17:47
  • 1
    You either need to populate the fields manually every time you open the form, rely on some form of data binding, or keep the instance of the form around instead of recycling it every time you close it. Kind of need more details to give a good answer. – Eric Andres Sep 04 '13 at 17:47
  • need to see the relevant code! strip out everything but code involved in this problem – Michael Sep 04 '13 at 17:47
  • Are you wanting to persist changes between application starts? You should be able to access the user settings. – Mark Hall Sep 04 '13 at 18:13
  • @EricAndres if I use `this.Hide();` it's "safe" for my application? – mafap Sep 04 '13 at 18:15
  • @MarkHall yes, when the user opens OptionsForm he should see the last settings he made – mafap Sep 04 '13 at 18:18
  • What about when he restarts the program – Mark Hall Sep 04 '13 at 18:20
  • 1
    @mafap Just as Mark said,it's best to use the settings file to store these values if you want to store them between application sessions. – devavx Sep 04 '13 at 18:25
  • 1
    @MarkHall I had misunderstood the question. When the program is restarted user have the default settings. Settings just persist when program is opened – mafap Sep 04 '13 at 18:26
  • @MarkHall sorry again, [this](http://stackoverflow.com/a/18620966/2208810) solved the holding issue but now i'm getting an Exception. Any sugestion? – mafap Sep 05 '13 at 16:04
  • You are newing up your FormOptions in your declarations, Try declaring it there, but new it up in your initializer assigning 'this` to it like you did before. – Mark Hall Sep 05 '13 at 16:29
  • @MarkHall I updated with what I have, I'm not sure if it is what you were talking about but it's still not working – mafap Sep 05 '13 at 17:45
  • I am assuming you used the example that Hans gave you. He is newing up the FormOptions in the declaration section of your main form. Leave the declaration there but new it up in the MainForms constructor instead. – Mark Hall Sep 05 '13 at 18:02
  • @MarkHall Yes, I'm using his example. Previously I was using `FormOptions formOptions = new FormOptions(this); formOptions.ShowDialog();` without his example and it was uploading the settings in main form but not holding them. Now it is holding the settings in Options form but not uploading. I'm getting an exception – mafap Sep 05 '13 at 19:24
  • 1
    @mafap Here is an [example Pastebin](http://pastebin.com/qcWtaxj9) of what I am trying to say. – Mark Hall Sep 06 '13 at 04:53
  • Perfect @MarkHall now it works! I was declaring optionsForm in a wrong place. Thanks for your time :) – mafap Sep 06 '13 at 10:14
  • @mafap You are welcome. Glad to be of help. – Mark Hall Sep 07 '13 at 22:11

6 Answers6

5

ShowDialog() was already made to support this. It is different from Show(), other than it being modal, it also prevents the form object from being disposed when the user closes it. So you can simply call ShowDialog() again, the controls keep their original values:

    private OptionsForm options = new OptionsForm();

    private void button1_Click(object sender, EventArgs e) {
        if (options.ShowDialog(this) == DialogResult.OK) {
            // etc..
        }
    }

    protected override void OnFormClosed(FormClosedEventArgs e) {
        options.Dispose();
        base.OnFormClosed(e);
    }
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • This works perfect. But... if I have this line in OptionsForm `this.mainForm.someLabel= someBox.Value.ToString();` (what it is needed and it was working before to change settings in MainForm) I get a `NullReferenceException` ("Object reference not set to an instance of an object."). How can it be fixed? – mafap Sep 05 '13 at 01:18
1

Well, you should pass these values to OptionsForm, feel free to write custom constructor for OpptionsForm and call it when you need.

dantix
  • 745
  • 1
  • 5
  • 14
1

One way to do it would be to just always keep a reference to your FormOptions and show the same instance rather than creating a new one every time. Or, if you don't want to do that, you can create an Options class that stores all of your options, which can then be stored and passed into any new instance you create thereafter. There's advantages and disadvantages to both so feel free to choose the option that best suits your needs.

public class MyOptions
{
    public String StringOption { get; set; }
    public int IntOption { get; set; }
}

Your FormOptions would then have a MyOptions property where you can set all of your options and retrieve them.

public class FormOptions : Form
{
    ...
    private MyOptions _options;
    public MyOptions Options 
    {
        get { return _options;}
        set
        {
            _options = value;
            // Set the Form's control values accordingly.
        }
    }
    ...
}

And finally, you would call it like so in your code:

    FormOptions optionsForm = new FormOptions();
    MyOptions savedOptions = new MyOptions(); // Probably don't want to create a new instance every time but I'm sure you get the idea here.
    optionsForm.Options = savedOptions;
    optionsForm.ShowDialog();

    // Get the new options after the form is closed.
    savedOptions = optionsForm.Options;
aleppke
  • 496
  • 4
  • 13
1

if you just want to keep only one numeric up/down control's value, then just pass it as a parameter in the constructor..

public FormOptions(MainForm -mainFrm, int curNumericValue)
{
    someBox.value = curNumericValue;
}

and instantiate the form with the value from the MainForm

private void button1_click(....)
{
    FormOptions formOptions = new FormOptions(this, Convert.toInt32(someLabel.text));
    formOptions.ShowDialog();
}
Abdul Saleem
  • 10,098
  • 5
  • 45
  • 45
0

Seems like you are calling an instance of the options form from a click event like this:

button1_click(object sender, EventArgs e)
{
    OptionsForm optForm = new OptionsForm();
    optForm.showDialog();
}

You have to create variable for the options form class within the Mainform class, instantiate it there, or in the constructor, and only call the ShowDialog() or Show() method within the button_Click event. Like this:

partial class MainForm:Form
{
    OptionsForm optForm;
    ............
    ............
    public MainForm()    //Constructor
    {
        initialiseComponent();
        optForm = new OptionsForm();
        ........
    }

    .......

    private button1_Click(object sender, EventArgs e)
    {
        optForm.Show();    // or ShowDialog()
    }
}

and use this.hide() instead of this.close() in the options form.. or else the form gets disposed..

Abdul Saleem
  • 10,098
  • 5
  • 45
  • 45
  • This won't work if you use `Show`. If you do that the form will be disposed when it is closed, and will just error out when you try to show it again. – Servy Sep 04 '13 at 18:20
  • You could. It would be a fair bit of work that you haven't even discussed. – Servy Sep 04 '13 at 18:23
0

Why not just make use of the "Settings" that are available within the build properties, and WinForms itself? Just have your settings form populate itself with these variables, and "set" them when you click OK. Then have the MainForm refresh from these settings once the SettingsForm has fully closed. Easy, no mess, and no passing variables between forms.

Overview: http://msdn.microsoft.com/en-us/library/k4s6c3a0.aspx

SO Question covering Settings: Save Settings in a .NET Winforms Application

It also has the added bonus that the values will be saved between sessions of the application.

Community
  • 1
  • 1
Lee Harrison
  • 2,306
  • 21
  • 32
  • [this comment](http://stackoverflow.com/questions/18620496/keeping-values-of-secondary-form#comment27411576_18620496) from the OP indicates he's not interested in persisting the data beyond the current execution of the program. – Servy Sep 04 '13 at 18:44
  • I missed that one, but... I'd simply rewrite the settings to the default values upon opening the application and this behavior is achieved. No reason to involve custom constructors or classes if it a just a simple settings window as he described it. – Lee Harrison Sep 04 '13 at 18:48
  • 1
    The settings options is designed for persisting data between application executions. If you don't want to do that, you shouldn't use it. It's doing a *lot* of work to persist that information, none of which is needed. No custom constructors nor classes are needed; one can simply persist the object itself, as seen in other answers, which is much easier still than this solution, and less error prone. – Servy Sep 04 '13 at 18:54