防止重复的 MDI 子窗体

13

如果特定的表单已经打开,有没有一种方法可以防止在MDI容器中打开它?

7个回答

36

您可以遍历OpenForms集合来检查是否已经存在给定类型的窗体:

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

Form newForm = new MyFormType();
newForm.MdiParent = this;
newForm.Show();

不要使用form.Activate(),而是使用form.WindowState = FormWindowState.Normal;与前者不同,后者即使窗口被最小化也能正常工作。 - EKanadily

3
据我所知,目前没有标准的方法。您需要自己实现。我会这样做:
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);
    }
}

如果线程安全是一个问题,需要添加适当的锁定代码。

线程安全不应该是一个问题,因为您只从单个线程访问GUI控件。 - vgru
你可以添加这是单例模式的实现。我更喜欢Fredrik Mörk的解决方案,它不违反SOC。 - Johannes Rudolph

1
这段代码有效。
    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();
    }

0

尽管这篇文章很老,但我认为这会提供一些帮助。

还需要处理表单被最小化的情况。 这是完整的示例:

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();

0

可以使用泛型(以下是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();
}

使用方法如下(在multipleInstances中指定false以防止它们)

OpenMDI<Form2>(false);

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

请按以下方式使用(对于bMultipleInstances指定False以防止它们)
Open_MDI(Of Form2)(False)

0

This code work for me in vb.net

 

对于每个打开的窗体,如果是指定的窗体类型,则激活该窗体并将其状态设置为正常。然后将其起始位置设置为 Windows 默认位置,并将其状态设置为最大化。

            Return
        End If    
    Next 
    form_name .MdiParent = Me
    form_name .Show()


0

这段代码在C#中对我有效

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接