Предотвращение дублирования дочерних форм MDI

Есть ли способ предотвратить открытие определенной формы в контейнере MDI, если эта форма уже открыта?


person user    schedule 12.10.2009    source источник


Ответы (6)


Вы можете взаимодействовать с коллекцией OpenForms, чтобы проверить, существует ли уже форма данного типа:

foreach (Form form in Application.OpenForms)
{
    if (form.GetType() == typeof(MyFormType))
    {
        form.Activate();
        return;
    }
}

Form newForm = new MyFormType();
newForm.MdiParent = this;
newForm.Show();
person Fredrik Mörk    schedule 12.10.2009
comment
вместо form.Activate() используйте form.WindowState = FormWindowState.Normal; в отличие от первого, последний будет работать, даже если это окно свернуто. - person EKanadily; 13.08.2014

AFAIK нет стандартного способа. Вам придется реализовать его самостоятельно. Я бы сделал это так:

class TheForm: Form
{
    private static TheForm Instance;

    private TheForm() // Constructor is private
    {
    }

    public static Show(Form mdiParent)
    {
        if ( Instance == null )
        {
            // Create new form, assign it to Instance
        }
        else
            Instance.Activate(); // Not sure about this line, find the appropriate equivalent yourself.
    }

    protected override OnFormClose(EventArgs e)
    {
        Instance = null;
        base.OnFormClose(e);
    }
}

Если вас беспокоит безопасность потоков, добавьте соответствующие locks.

person Vilx-    schedule 12.10.2009
comment
Безопасность потоков не должна быть проблемой, поскольку доступ к элементам управления GUI осуществляется только из одного потока. - person Groo; 12.10.2009
comment
вы могли бы добавить, что это реализация одноэлементного шаблона. Я предпочитаю решение Фредрика Мёрка, оно не нарушает SOC - person Johannes Rudolph; 12.10.2009

этот код работает

    private void openToolStripMenuItem_Click(object sender, EventArgs e)
    {
        foreach (Form form in Application.OpenForms)
        {


            if (form.GetType() == typeof(Form2))
            {
                form.Activate();
                return;
            }
        }

        Form2 newForm = new Form2();
        newForm.MdiParent = this;
        newForm.Show();
    }
person user3163424    schedule 05.01.2014

Хотя этот пост очень старый, я подумал, что это добавит помощи.

Необходимо обрабатывать, если форма также сведена к минимуму. Вот полный пример:

foreach (Form form in this.MdiChildren)
{
    if (form.GetType() == typeof(frmMain))
    {
        if (form.WindowState == FormWindowState.Minimized)
        {
            form.WindowState = FormWindowState.Normal;
        }
        form.Activate();
        return;
    }
}
Form frm = new frmMain();
frm.MdiParent = this;
frm.Show();
person Avijit    schedule 17.06.2016

Метод можно реализовать с помощью Generics (ниже опций C# и VB.net), что может быть полезно, если необходимо открыть разные MDI-формы.

C#

private void OpenMDI<T>(bool multipleInstances)
    where T : Form, new()
{
    if (multipleInstances == false)
    {
        // Look if the form is open
        foreach (Form f in this.MdiChildren)
        {
            if (f.GetType() == typeof(T))
            {
                // Found an open instance. If minimized, maximize and activate
                if (f.WindowState == FormWindowState.Minimized)
                {
                    f.WindowState = FormWindowState.Maximized;
                }

                f.Activate();
                return;
            }
        }
    }

    T newForm = new T();
    newForm.MdiParent = this;
    newForm.Show();
}

Используйте его следующим образом (укажите false в multipleInstances, чтобы предотвратить их)

OpenMDI<Form2>(false);

ВБ.NET

Public Sub Open_MDI(Of T As {New, Form})(bMultipleInstances As Boolean)
    If bMultipleInstances = False Then
        For Each f As Form In Me.MdiChildren
            If TypeOf f Is T Then
                If (f.WindowState = FormWindowState.Minimized) Then
                    f.WindowState = FormWindowState.Maximized;
                End If

                f.Activate()
                Exit Sub
            End If
        Next
    End If

    Dim myChild As New T()
    myChild.MdiParent = Me
    myChild.Show()
End Sub

Используйте его следующим образом (укажите False для bMultipleInstances, чтобы предотвратить их)

Open_MDI(Of Form2)(False)
person Dr Yunke    schedule 14.04.2018

Этот код работает для меня на С#

      private void btn1_Click(object sender, EventArgs e)
            {
               Form2 new_form = new Form2();
                if (new_form.visible)
                    new_form.Show();
                else
                    new_form.ShowDialog();
            }
person mamal    schedule 16.12.2018