Introduction
When I started with VB.NET a few years ago, one of the things I missed was how to deal with forms where you only want one instance open at the same time. I read a lot of articles concerning Singleton forms etc, which was all complicated and the result was not easy to use. At the end I found a very simple way to do this. Maybe too easy !
Solution
The trick is realy very simple. I just make a class with Public Shared variables with as
type the Forms itself.
Public Class clsGlobals
#Region "Singleton Forms"
Public Shared frmStockSelection As frmStockSelection
Public Shared frmSettings As frmSettings
#End Region
End Class
These public shared variables will be usable eveywhere in your code. You do not create a new instance from this class. Call the variable by using the class name as shown in the next bit of code.
The code to open the Singleton Form
is also very simple. The only thing to do is to check if the variable is not nothing, if not create a new instance. You have to use Focus
to get your form to the foreground in case an instance was already existing but maybe hidden behind other windows.
If clsGlobals.frmSettings Is Nothing Then
clsGlobals.frmSettings = New frmSettings
End If
clsGlobals.frmSettings.Show()
clsGlobals.frmSettings.Focus()
One more thing we have to do to make this work, the variable must be set back to nothing
in case we close the form. This we can do in the Dispose
sub of the form. After Dispose
we can safely set the Form
to nothing
.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
clsGlobals.frmSettings = Nothing
End Sub
Another option is to keep the Form
open in memory. This is very handy for Forms, like a little calculator for example where you don't want to start with a clear form every time.
The way to do this is to avoid the close the form and hide it. e.Cancel = True
will stop the form from closing.
Private Sub frm_Closing(ByVal sender As Object, _
ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
Me.Hide()
e.Cancel = True
End Sub
Maybe the purist readers will not 100% agree with this approach, but for me it works very well.