Добавлено или удалено определение формы MDI с дочерней формой

Есть ли событие, которое я могу использовать, чтобы определить, была ли дочерняя форма добавлена ​​или удалена из родителя MDI?


person Malfist    schedule 11.02.2009    source источник


Ответы (7)


Нет, нет. Вам нужно будет создать подкласс Form и предоставить определенные события, которые укажут, когда будет добавлен дочерний элемент, а затем направить все вложения дочерних форм через метод, который подключит дочернюю форму, а также вызовет событие.

person casperOne    schedule 11.02.2009
comment
Не могли бы вы объяснить, как это сделать? - person Malfist; 11.02.2009
comment
@Malfist: вы должны расширить форму, добавить метод AddMdiChild, а затем, когда он вызывается, вы должны установить MdiParent формы, переданной самой себе, а затем запустить событие. - person casperOne; 11.02.2009
comment
Как я узнаю, закрылся ли ребенок? - person Malfist; 11.02.2009
comment
@Malfist: присоединяйтесь к событиям Closed/Closing дочернего элемента при вызове AddMdiChild. - person casperOne; 11.02.2009
comment
Но у детей будут свои собственные события Closed/Closing, могу ли я добавить еще один обработчик событий? - person Malfist; 11.02.2009
comment
@Malfist: Вы бы не заменили его. Обработчик события будет добавлен к любому уже существующему. - person casperOne; 11.02.2009

Да. В основной форме MDI подключитесь к событию MdiChildActivated.

Вот так:

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.MdiChildActivate += new EventHandler(Form1_MdiChildActivate);
        }

        void Form1_MdiChildActivate(object sender, EventArgs e)
        {
            MessageBox.Show("Activated");
        }

        private void addToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form form2 = new Form2();
            form2.MdiParent = this;
            form2.Show();
        }
    }

И это событие сработает, когда дочерняя форма активируется или деактивируется.

person Chris Holmes    schedule 11.02.2009
comment
как я могу сказать, если он приходит или уходит? Просто проверьте список детей и посмотрите, есть ли там отправитель? - person Malfist; 11.02.2009
comment
Хм, это может не сработать. Если я повторно активирую/сосредотачиваюсь на открытой форме, она также вызывает событие. - person Malfist; 11.02.2009
comment
Я получил это, поле идентификатора в базовом классе для всех детей. - person Malfist; 11.02.2009
comment
Ваша форма MDI также будет иметь множество дочерних элементов. Имущество MdiChildren. Вы можете проверить количество в этом списке, чтобы узнать, была ли форма только что добавлена, удалена или сфокусирована (счетчик останется прежним). - person Chris Holmes; 11.02.2009
comment
Это связано с тем, что коллекция MdiChildren не обновляется до тех пор, пока дочерняя форма полностью не исчезнет. Другими словами, MdiChildActivated срабатывает до того, как дочерний элемент исчезнет. Таким образом, он работает для обнаружения добавления формы, но отстает на единицу, когда форма удаляется. - person Chris Holmes; 12.02.2009

Подключите событие MdiChildActivate и сохраните список распознанных детей. Когда активируется новая форма, также подключите событие FormClosed.

private List<Form> ChildFormList = new List<Form>();

private void MyForm_MdiChildActivate(object sender, EventArgs e)
{
    Form f = this.ActiveMdiChild;

    if (f == null)
    {
        //the last child form was just closed
        return;
    }

    if (!ChildFormList.Contains(f))
    {
        //a new child form was created
        ChildFormList.Add(f);
        f.FormClosed += new FormClosedEventHandler(ChildFormClosed);
    }
    else
    {
        //activated existing form
    }
}

private void ChildFormClosed(object sender, FormClosedEventArgs e)
{
    //a child form was closed
    Form f = (Form)sender;
    ChildFormList.Remove(f);
}
person lc.    schedule 20.05.2009
comment
Вам также нужно отписаться от события, иначе у вас будет утечка памяти. - person Andriy K; 14.01.2016

Я понял, что это слишком поздно, однако, поскольку ответы здесь помогли мне решить эту проблему, я бы упомянул, что это отлично работает с использованием массива MdiChildren в .net 4. Единственное, что вам нужно сделать, это проверить, удаляется ли форма или удаляется чтобы сказать, закрывается ли он.

ie:

    private void frmContainer_MdiChildActivate(object sender, EventArgs e)
    {
        tabWindows.RefreshLayout(this.MdiChildren.ToList());
    }

    public void RefreshLayout(List<Form> forms)
    {
        this.nextButtonLeft = 1;
        panel1.Controls.Clear();
        foreach (Form frm in forms)
        {
            if (!(frm.Disposing || frm.IsDisposed)) { addButton(frm); }
        }
    }
person Ryan Buddicom    schedule 16.08.2012

Да, вы можете легко обнаружить добавление форм в MDI Form.

Если пометить ParentForm как MdiContainer, задав для IsMdiContainer значение true, возникнет событие ParentForm.ControlAdded для добавления элемента управления "MdiClient" в родительскую форму. Таким образом, при добавлении MdiClient в родительскую форму MDI мы можем сгенерировать событие ControlAdded для элемента управления MdiClient, как показано ниже:

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

Нам нужно поднять MdiClient.ControlAdded, как показано ниже:

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

      }

По умолчанию дочерние формы MDI добавляются в коллекцию элементов управления MdiClient в родительской форме. Таким образом, при установке значения ChildForm.MdiParent в качестве родительской формы возникает событие ControlAdded для MdiClient.

void MdiClient_ControlAdded(object sender, ControlEventArgs e)
{

}

Таким образом, используя описанный выше метод, вы можете узнать, какие дочерние формы MDI добавлены в родительские формы MDI. Таким образом, вы можете добавить событие ControlRemoved для элемента управления MdiClient, чтобы узнать, какие дочерние формы удалены из формы MDI.

Надеюсь, что это поможет вам.

person Jagadeesan    schedule 23.03.2017

Поскольку событие MdiChildActivate запускается до того, как дочерняя форма MDI фактически закрывается, и, следовательно, недостаточно информации, чтобы определить, действительно ли дочерняя форма MDI активирована или закрыта, я выбрал другой подход для решения проблемы.

Я обнаружил, что событие ParentChanged срабатывает в дочерней форме MDI, когда она закрыта.

public class MdiParentForm : Form
{
    // ...

    private Form CreateMdiChildForm()
    {
        var form = new MdiChildForm
        form.ParentChanged += MdiFormParentChangedHandler;
        form.MdiParent = this;
        return form;
    }

    private void MdiFormParentChangedHandler(object sender, EventArgs args)
    {
        var form = sender as Form;
        if (form != null)
        {
            if (form.MdiParent != null)
            {
                // MDI child form will activate
                // ... your code here
            }
            else
            {
                // MDI child form will close
                form.ParentChanged -= MdiFormParentChangedHandler;
                // ... your code here
            }
        }
    }

    // ...
}
person Valvestino    schedule 31.01.2017

Недавно я хотел примерно определить, когда не было открытых MDI-детей, чтобы я мог отображать панель с множеством кнопок «что делать» только тогда, когда не было открытых дочерних форм. (просто исследую дизайнерскую идею).

Мое окончательное решение было элегантно простым — добавить таймер в родительскую форму и запускать таймер каждый раз, когда событие MdiChildActivate определяет, что открыта 1 дочерняя форма.

    private void MyForm_MdiChildActivate(object sender, EventArgs e)
    {
        this.panel_Tools.Visible = false;
        if (this.MdiChildren.Count() == 1)
        {
            this.timer_WindowsCounter.Start();
        }
        else
        {
            this.timer_WindowsCounter.Stop();
        }

    }


    private void timer_WindowsCounter_Tick(object sender, EventArgs e)
    {
        if (this.MdiChildren.Count() == 0)
        {
            this.panel_Tools.Visible = true;
            this.timer_WindowsCounter.Stop();
        }
    }
person Robbie    schedule 17.01.2013
comment
Не очень элегантное решение. - person rolls; 07.01.2017