在MDI中从子级访问父窗体的元素

1 c#

问题是我需要从其他表单访问不同的表单元素,或者例如从某些子窗口访问MdiContainer表单菜单并使用它进行一些操作.如何正确实现这样的功能?我现在正在使用Windows窗体.

下面的一些示例代码演示了我是如何尝试这样做的.

Form1(是一个Mdi容器)

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

    private void menu2ToolStripMenuItem_Click(object sender, EventArgs e)
    {
        Form2 chWin = new Form2(this);
        chWin.Show();
    }

    public void disableMenu()
    {
        menuStrip1.Enabled = false;
    }
}
Run Code Online (Sandbox Code Playgroud)

Form2(Form1的孩子)

public partial class Form2 : Form
{
    private Form1 parent;

    public Form2(Form1 parent)
    {
        InitializeComponent();
        MdiParent = parent;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        parent.disableMenu();
    }
}
Run Code Online (Sandbox Code Playgroud)

异常:对象引用未设置为对象的实例

尝试谷歌,但实际上没有任何帮助我的机会.

提前致谢!

Mik*_*nen 6

您正在尝试访问尚未初始化的成员.在Form2构造函数中,您只是设置MdiParent属性,但您忘记了这一行:

this.parent = parent;
Run Code Online (Sandbox Code Playgroud)

此外,您不必将Form1传递给Form2的构造函数.您可以通过在显示Form2之前设置MdiParent来避免这种情况:

private void menu2ToolStripMenuItem_Click(object sender, EventArgs e)
{
    Form2 chWin = new Form2(this);
    chWin.MdiParent = this;
    chWin.Show();
}
Run Code Online (Sandbox Code Playgroud)

然后在Form2中,您可以通过将MdiParent转换为Form1来调用Form1的方法:

private void button1_Click(object sender, EventArgs e)
{
    ((Form1)MdiParent).disableMenu();
}
Run Code Online (Sandbox Code Playgroud)

虽然不是这样做,但您可能应首先创建一个接口:

public interface IMenuHandler
{
    void DisableMenu();
}
Run Code Online (Sandbox Code Playgroud)

然后使Form1实现此接口并将其传递给其构造函数中的Form2.Form2的整个实现将如下所示:

public partial class Form2 : Form
{
    private IMenuHandler menuHandler;

    public Form2(IMenuHandler handler)
    {
        InitializeComponent();
        this.menuHandler = handler;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        menuHandler.DisableMenu();
    }
}
Run Code Online (Sandbox Code Playgroud)

这样,您的Form2不直接依赖于Form1,您更容易更改任何一个表单.