JBurace
JBurace

Reputation: 5623

Call parent form function?

I have a C# window program with 2 forms. The base form (Form1) has a function to refresh (RefreshView) the view. Clicking buttons will bring up Form2. After clicking say an "Apply" button on Form2, how can I call RefreshView function that exists in Form1? Both forms are open by the user.

Form1 code in Form1.cs:

namespace MonitorCSharp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public void RefreshView()
        {
            //refresh code etc
        }
    }
}

Form2 in Form2.cs:

namespace MonitorCSharp
{
    public partial class Form2 : Form
    {
        public Form2(String args)
        {
            InitializeComponent();
            form2Text = args;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            this.Close();
            //I want to refresh here
        }
}

I have tried various code including:

((Form1)this.ParentForm).RefreshView();

To call the refresh function, but so far everything gives me a runtime error. Am I missing something?

I get no compile errors. The runtime error is:

A first chance exception of type 'System.NullReferenceException' occurred in MonitorCSharp.exe
An unhandled exception of type 'System.NullReferenceException' occurred in MonitorCSharp.exe
Additional information: Object reference not set to an instance of an object.

Upvotes: 1

Views: 3334

Answers (4)

A876
A876

Reputation: 518

After some trial and error, this works for me. (The called function is not static.) (VS2010.)

Main form:

internal partial class Form1 : Form
{
    ...
    using (Form2 f2 = new Form2(this) { Icon = this.Icon })  // Instantiate the child form.
    {
        f2.someUpDown.Maximum = foo;  // (Optionally write data to the child form.)
        f2.ShowDialog();  // Show the child form and wait until it closes.
        ...
        bar = f2.someUpDown.Value;  // (Optionally read data from the [closed] child form.)
        ...
    }  // (Destroy the child form.)

Child form:

internal partial class Form2 : Form
{
    private Form1 _parent;  // (need this variable)

    internal Form2(Form1 parent)  // (the default constructor)
    {
        InitializeComponent();

        _parent = parent;  // Save the argument.
        ...
        someUpDown.Maximum = Form1.foo;  // (Optionally read data from the parent form.)
        Form1.bar = someUpDown.Value;  // (Optionally write data to the parent form.)
        ...
        _parent.myProcedure(arg1);  // (Optionally call myProcedure() in the parent form.)
        ...
    }

    private void SomeButton_Click(object sender, EventArgs e)  // (callback from event loop)
    {
        ...
        someUpDown.Maximum = _parent.foo;  // (Optionally read data from the parent form.)
        _parent.bar = someUpDown.Value;  // (Optionally write data to the parent form.)
        ...
        _parent.myProcedure(arg1);  // (Optionally call myProcedure() in the parent form.)
        ...
    }

If I change private Form1 _parent; to private Form _parent;, it's invalid.

If I change internal Form2(Form1 parent) to internal FormTubeSelection(Form parent), it's invalid until I also change _parent = parent; to _parent = (Form1)parent;

Almost everywhere, you access Form1 fields and methods with the _parent. prefix; the Form1. prefix is invalid. EXCEPTION: Access Form1 fields in the constructor as Form1.foo; _parent.foo is invalid there.

If you only need to call the procedure in the main form when the child form closes, it is easier to call it from the main form, right after f2.ShowDialog(). If the call is conditional, code in the main form can test data in the child form and/or the return value of f2.ShowDialog(), until you dispose of f2.

Upvotes: 0

Servy
Servy

Reputation: 203802

The parent form can attach an event handler to it's child's FormClosed event handler to execute code when it's closed:

public partial class Form1 : Form
{
    public void Foo()
    {
        Form2 child = new Form2();
        child.FormClosed += (s, args) => RefreshView();
        child.Show();
    }

    public void RefreshView()
    {
        //refresh code etc
    }
}

Upvotes: 5

Alex Walker
Alex Walker

Reputation: 2356

Most likely you simply need to pass a reference to Form1 when you construct Form2.

Find the constructor for Form2, that is most likely:

public Form2()
{
    InitializeComponent();
}

And add a parameter to it, so it now reads:

public Form2(Form form1)
{
    InitializeComponent();
    _form1 = form1;
}

And add a private field in your Form2 class:

private Form1 _form1;

Then when you create Form2 from your Form1.cs, you should use

new Form2(this);

where "this" represents the current instance of Form1.

And to access RefreshView from Form2, you call

_form1.RefreshView();

Upvotes: 2

Eric J.
Eric J.

Reputation: 150108

You are getting a NullReferenceException.

Chances are very good that you never initialized this.ParentForm.

When Form1 creates Form2, ensure that you set that property appropriately.

One way to do that is to create a constructor for Form2 that takes an instance of its parent, e.g.

public Form2(Form1 parent)
{
    InitializeComponent();
    this.ParentForm = parent;
}

When creating the child form from the parent form,

Form2 child = new Form2(this);

Upvotes: 0

Related Questions