C# MDI Parent detect when MDI Child is closing?

2019-02-23 01:05发布

问题:

I'm attempting to detect, on the MDI parent, when my MDI child form closes, and react accordingly. The MDI parent shouldn't do anything until the MDI child closes. Here is my code, I'm unsure as to what I'm doing wrong, but the form closed event method I added is never being called...

The following code is in the MDI parent class, if that wasn't obvious.

    private void keyValidation()
    {
        if (Properties.Settings.Default.Unlock == true)
            return;
        else
        {
            menu.Enabled = false;
            statusStrip.Enabled = false;

            ValidationForm vf = new ValidationForm();
            vf.MdiParent = this;
            vf.Show();
            vf.FormClosed += new FormClosedEventHandler(validationForm_FormClosed);
        }
    }

    void validationForm_FormClosed(object sender, FormClosedEventArgs e)
    {
        MessageBox.Show("Got here");
        if (Properties.Settings.Default.Unlock == true)
        {
            menu.Enabled = true;
            statusStrip.Enabled = true;
        }
    }

Thanks for any help!

回答1:

While this doesn't really address the problem you're referring to, judging from the use case, you may want to consider opening the Validation form as a modal dialog instead of as an MDI child.

You can do this using the form's ShowDialog() method where you have Show() now. Keep in mind that ShowDialog() can also return a DialogResult if you assign them to buttons on the other form.



回答2:

Maybe, just maybe, you have a CHILD form that HIDES not CLOSES. Try hooking VisibleChanged and see what happens.

Also, FormClosing will allow you to cancel closing, and FormClosed doesn't give you that option.



回答3:

Don't use the Closed Event. Instead, use the FormClosing event:

private void frmMain_FormClosing(object sender, FormClosingEventArgs e){
  if (MessageBox.Show("Are you sure you want to Exit", "Confirmation", MessageBoxButtons.YesNo,MessageBoxIcon.Information) == System.Windows.Forms.DialogResult.No) {
    e.Cancel = true;
  }
}


回答4:

When mark the ParentForm as MdiContainer by setting the IsMdiContainer to true, the ParentForm.ControlAdded event raised for adding the "MdiClient" control to the parent form. So when adding MdiClient to parent MDI form, we can raise the ControlAdded event for the MdiClient control as like below,

  public ParentForm()
  {
    InitializeComponent();
    this.ControlAdded += Form1_ControlAdded;
    this.IsMdiContainer = true;

We need to raise the MdiClient.ControlAdded as like the below,

    void Form1_ControlAdded(object sender, ControlEventArgs e)
      {
           if(e.Control is MdiClient)
                e.Control.ControlAdded += MdiClient_ControlAdded;

      }

By default the MDI Child forms are added into the controls collection of the MdiClient in Parent form. So when set the ChildForm.MdiParent value as Parent form, the ControlAdded event for the MdiClient will raise.

void MdiClient_ControlAdded(object sender, ControlEventArgs e)
{
    if (e.Control is Form)
        {
            var form = e.Control as Form;
            form.FormClosing += form_FormClosing;
            form.FormClosed += form_FormClosed;
        }
}

In this above MdiClient_ControlAdded method raises when child form added into the Parent MDI form. So by raising the FormClosing and FormClosed events for child forms you can easily detect whether the child form is closed or not.



回答5:

Why you are doing so many things when you can just invoke an event handler of MDI Parent to MDI Child?

Suppose I want to do certain things when my child will be activated or deactivated. You just need to declare some event handlers of MDI Parent (as e.g. SetupToolStripMenu_PlantMasterRecipe) and mention some logic inside that what you want to do. By this way, you can control each object behaviour of MDI Child from MDI Parent.

Here objB is my Child form and I am writing this code inside MDI Parent:

objB.MdiParent = this;

objB.Activated += SetupToolStripMenu_PlantMasterRecipe;

objB.Deactivate += DisposeToolStripMenu;

objB.Show();


回答6:

On mdiparent make a public function

public void MakeMenuVisible()
{
MainMenu.visible = true;
}

Then on childform you can run the function like this

private void ChildForm_FormClosed(object sender, FormClosedEventArgs e)
{
//Cast MdiParent to Mainform
((mainform)this.MdiParent).MakeMenuVisible();  
}