Stop Multiple Instances of Child Form

Hi,
i want to stop multiple instances of child forms in a MDI application, can anyone suggest what can i do  my code is like this.

Private Sub MenuItem5_Click(ByVal sender As System.Object, ByVal e As    System.EventArgs) Handles MenuItem5.Click
        Dim b As Form3
        b = New Form3
        b.Show()
        b.MdiParent = Me
        b.Dock = DockStyle.Fill
End Sub

Thanks in advance,
Ajay


Answer this question

Stop Multiple Instances of Child Form

  • Isaac1

    try declaring it outside of your method and changing your code a little bit...


    Private b As Form3

    Private Sub MenuItem5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem5.Click 
         If b Is Nothing Then
              b = New Form3
              b.MdiParent = Me 
              b.Dock = DockStyle.Fill 
         End If
         b.Show() 
    End Sub 

  • Newbs

    It's probably also a good idea to make the form constructor private.

    I got the solution from :

    George Shepherd's
    Windows Forms FAQ

    http://www.syncfusion.com/FAQ/WinForms/FAQ_c4c.asp#q521q

    32.4 How do I check to see if a child form is already displayed so I don't have two instances showing

  • Javan

    Here is what i've done or do usually.  I also add the following:

    form = nothing 

    In the close event on the child form.

    Friend fMDI As MDI
    Friend fTracker As frmTracker
    Friend fAddItems As frmAddItems

    Friend Sub showFormTracker()
         If fTracker Is Nothing Then
              fTracker = New frmTracker
              fTracker.MdiParent = fMDI
              fTracker.Show()
              Else
                   fTracker.Activate()
         End If
    End Sub

    This is inside a module btw.

  • CindyK

    Sorry this is in C#.

    But I use a singleton pattern to solve this problem.

    1. In the child form I declare a static variable.

        private static frmChild childForm; 

    2. Define a public static property to return an instance of the form

       public static frmChild CurrentInstance 
       { 
        get 
             { 
    if (childForm == null) 
     childForm = new frmChild(); 
     return childForm; 
              } 
        }

    3. In the Main form call the static property of the child form class

        frmChild fChild = frmChild.CurrentInstance; 
        fChild.MdiParent = this; 
        fChild.Show(); 

  • e6henke

    I am trying to follow your example. I use a mdi form to call 2 seperate forms a Process  and  maintenance from.

    I use :
     Private Sub ProcessItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ProcessItem.Click
            Dim frm As New frmProcess()
            frm.MdiParent = Me
            frm.Show()

        End Sub

    can you give me an idea of how to modify this code to make sure I only have one instance of each form open at one time

    thanks

  • Riaz Ahmed

    Hi, I'm new to MDI. Ken, I totally agree with you comparing the types.

    The only problem I've got is that if the child form is closed (by click X button or close button), it seems that the child form is hide, so "childForm.Activate()" doesn't work.

    Support I have a ParentForm, I call ChildForm. In this child form, I have a datagrid, when I click Edit button (on ChildForm), I show frmProcess to show and let user Edit values on CURRENT DATAGRID'S ROW. It's mean frmProcess to be in a sublevel child.

    so simply I set:

    (this is in ChildForm)
    private frmProcess as frmEditCurrentGridRow

    private sub EditButton_Click(...)
            ' Parent form contains frmProcess   
            dim fc as Form
            for each fc in Me.MdiParent.MdiChildren
                  If fc Is frmProcess Then
                       If fc.WindowState = FormWindowState.Minimized Then
                             fc.WindowState = FormWindowState.Normal
                       End If
                       fc.Show()
                       fc.Focus()
                       Return
                  End If
            next

            ' If not, create new Instance

            If (frmProcess Is Nothing) Then
                frmProcess = New frmEditCurrentGridRow
                frmProcess .MdiParent = Me.MdiParent
                frmProcess .Show()
                frmProcess .Focus()
            End If

    end sub

    I don't know what's wrong with these above code, when I run this and click Edit button, it's OK, I minimize frmProcess and click Edit again, it's work. But when I close frmProcess by click X button (or Close button), and then I click Edit again, nothing happen.

    I set a*space
    space*point and see that althrough closed, the frmProcess is still there (of course because I didn't call Dispose), it's mean NOT (frmProcess Is Nothing). I really don't know where to put Dispose(), how to set frmProcess to Nothing. PLEASE HELP !!!

    Another error: when run this 4, 5 times, I've got an "Out of memory" exception (my PC is 2.8 Mhz, 512 MB RAM, 80 GB HD), the only way is restart :(

    Thank for reading this, my English is not so good, so I have to give details, sorry for that!
      




  • Juney Moon

    I couldn't stop myself--I'm going to suggest a few code changes, if you don't mind. First of all, you don't need to create an instance of frmProcess if there's already a child of this type, so I moved that code lower. In addition, rather than comparing the names of the forms, I changed the code to compare the types. It runs faster, and it's less prone to possible problems (I always feel uncomfortable comparing strings, when anything else will do). Here's an alternative version:

        Dim formExists As Boolean = False

        For Each childForm As Form In Me.MdiChildren
          If TypeOf childForm Is frmProcess Then
            formExists = True
            childForm.Activate()
            Exit For
          End If
        Next

        If Not formExists Then
          Dim frm1 As New frmProcess
          frm1.MdiParent = Me
          frm1.Show()
        End If

    If you want to make this generic (that is, have it work for any type of form class) it gets more complicated, but it's possible. If you find that you want to have code like this for more than one child form, it's worth considering. 

  • Irfan Kalkoti

    Dim frm1 As New frmProcess()
            Dim childForm As Form
            Dim formExists As Boolean = False

            For Each childForm In Me.MdiChildren
                If childForm.Name = frm1.Name Then
                    formExists = True

                    childForm.Activate()

                    Exit For
                End If
            Next

            If Not formExists Then
                frm1.MdiParent = Me
                frm1.Show()
            End If

    I modifed the code as follows and it seems to work. I don't understand all the code yet but If it works thats was the goal.

  • Marcelo Glauco

    As an alternative approach, consider using a factory class to create all your forms. 

    Create a class (eg class Launcher) which contains a hashtable. Use a function called, say, Launcher.OpenForm(ID as striing), to open all your forms. 

    Each form needs a unique ID, but this approach allows you to open exactly one form with a specified ID. So, if you have a collection of things you can edit (documents, say) and each one has a unique ID (say, a filename or guid) then this allows you to open one editor per document. 

    Some snipppets of code cobbled together;

    class Launch

        private sub new()  '' don't allow instance creation
        end sub

        Private shared forms As New Hashtable()

        Public shared Function OpenPage(ByVal thing As Thing) As Boolean

            Dim f As Form
            Dim existingFormValid As Boolean

            If validFormExists(thing.ID) Then
                f = CType(forms.Item(thing.ID), Form)
            Else
                f = New FThingDetails(thing)
                If forms.ContainsKey(thing.ID) Then forms.Remove(thing.ID)
                forms.Add(thing.ID, f)
            End If

            f.Show()
            f.Activate()

        End Function


        Public shared Sub ClosePage(ByVal ID As String)
            If validFormExists(ID) Then
                Dim f As Form = CType(forms.Item(ID), Form)
                forms.Remove(ID)
                f.Close()
            End If
        End Sub

        Private Function validFormExists(ByVal ID As String) As Boolean
            Return forms.ContainsKey(ID) AndAlso (forms.Item(ID) Is Nothing = False) AndAlso CType(forms.Item(ID), Form).IsDisposed = False
        End Function

    End Module

  • joelm9898

    Thanks for the help. I just changed the code a little bit..

    I wanted the child form to show on a click event.

               Dim frm1 As New Form1
                Dim childForm As Form
                Dim formExists As Boolean = False

                For Each childForm In Me.MdiChildren
                    If childForm.Name = form1.Name Then
                        formExists = True

                             childForm.Activate()

                        Exit For
                    End If
                Next

                If Not formExists Then
                    from1.MdiParent = Me
                    form1.Show()
                End If

  • Chris Mullins

    Or, if you know you'll be working in VB.NET, you can declare the variable using the Static keyword inside the procedure. That way you can restrict the scope of the variable more carefully. Otherwise, Erik's code stays the same.
  • KirkAtCenterstance

    Below is a sample of how I have been accomplishing this.  I am open to better ways of accomplishing this.

            Dim childForm As Form
            Dim formToOpen As New OpenThisForm
            Dim formExists As Boolean = False

            For Each childForm In Me.MdiChildren
                If childForm.Name = formToOpen.Name Then
                    formExists = True
                    'Show a message
                    Exit For
                End If
            Next

            If Not formExists Then
                formToOpen.MdiParent = Me
                
                formCaseSearch.Show()
            End If

  • JCNationwide

    This is a problem in many respects because if you have a toolbar that launches different windows based on the button click, you'd have to either handle everyone separatley with the associated code, or*space
    space*it into two sections. One that checks the MdiChildren collection to see if the form already exists, and the other than creates a new form if it doesn't. The problem with this approach is that hte debugger gets VERY flaky if you declare a form as Form theForm = null;

    And then in a select do this:

    theForm = new SomeSpecificForm();
    theForm.MdiParent = this;
    theForm.Show();

    It will stop debugging to the line of code that causes the error, and instead error back to the Application.Run line of your application.

    The really frustrating part is that this isn't consistantly the case either.

  • Roman Sedov

    I am have a mdi container with child forms. Every time I open a child form all the other forms already open hide behind the active child form. 

    I used this code to open the form in the mdi container. 

    Dim frm as new Form1 
    Dim frmmain as frmmain 

    frmmain = me.mdiparent 

    frm.mdiparent = frmmain 
    frm.show 

    But how do I get this form to display again without creating a instance of this form. After I've already open a few other child forms.

  • Stop Multiple Instances of Child Form