调用父窗体函数

本文关键字:函数 窗体 调用 | 更新日期: 2023-09-27 18:36:48

我有一个有 2 个表单的 C# 窗口程序。基本窗体 (Form1) 具有刷新 (RefreshView) 视图的功能。单击按钮将调出 Form2。在 Form2 上单击"应用"按钮后,如何调用 Form1 中存在的RefreshView函数?这两种表单都由用户打开。

Form1.cs中的 Form1 代码:

namespace MonitorCSharp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        public void RefreshView()
        {
            //refresh code etc
        }
    }
}

表格2 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
        }
}

我尝试了各种代码,包括:

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

调用刷新函数,但到目前为止,一切都给了我一个运行时错误。我错过了什么吗?

我没有收到编译错误。运行时错误为:

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.

调用父窗体函数

父窗体可以将事件处理程序附加到其子项的FormClosed事件处理程序,以便在关闭时执行代码:

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
    }
}

很可能只需要在构造 Form2 时传递对 Form1 的引用。

查找 Form2 的构造函数,最有可能:

public Form2()
{
    InitializeComponent();
}

并为其添加一个参数,因此它现在显示为:

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

并在 Form2 类中添加一个私有字段:

private Form1 _form1;

然后,当您从 Form1.cs 创建 Form2 时,您应该使用

new Form2(this);

其中"this"表示 Form1 的当前实例。

要从 Form2 访问 RefreshView,请调用

_form1.RefreshView();

你得到一个 NullReferenceException。

很有可能您从未初始化过this.ParentForm

当 Form1 创建 Form2 时,请确保正确设置该属性。

一种方法是为 Form2 创建一个构造函数,该构造函数采用其父级的实例,例如

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

从父窗体创建子窗体时,

Form2 child = new Form2(this);

经过一些试验和错误,这对我有用。(调用的函数不是静态的。(VS2010.

主要形式:

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.)

子表格:

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.)
        ...
    }

如果我private Form1 _parent;更改为private Form _parent;,它是无效的。

如果我将internal Form2(Form1 parent)更改为internal FormTubeSelection(Form parent),则在我也将_parent = parent;更改为_parent = (Form1)parent;之前,它是无效

几乎在所有地方,您都可以使用_parent.前缀访问 Form1 字段和方法;Form1.前缀无效。例外:以Form1.foo访问构造函数中的 Form1 字段; _parent.foo在那里无效。

如果只需要在子窗体关闭时调用主窗体中的过程,则在 f2.ShowDialog() 之后立即从主窗体调用该过程会更容易。如果调用是有条件的,则主窗体中的代码可以测试子窗体中的数据和/或返回值 f2.ShowDialog(),直到释放 f2。