How to create generate Form - vb.net

I have to write a log of codes when open new Windows Form.
Can I make a function to run this command? by call it with "fDeliveryNotation" only
Case "Delivery Notation"
If Application.OpenForms().OfType(Of fDeliveryNotation).Any Then
For Each f As Form In Application.OpenForms
If TypeOf f Is fDeliveryNotation Then
f.Activate()
Exit For
End If
Next
Else
Dim NewMDIChild As New fDeliveryNotation
NewMDIChild.MdiParent = Me
NewMDIChild.Show()
NewMDIChild.WindowState = FormWindowState.Maximized
End If
Code for open new window when window not exist if exist activate it.

Generic function:
Public Sub OpenForms(Of T As {New, Form})()
Dim tForms = Application.OpenForms.OfType(Of T)()
If tForms.Any() Then
tForms.Select(Function(x) x).First().Activate()
Else
Dim NewMDIChild As New T
NewMDIChild.MdiParent = Me
NewMDIChild.Show()
NewMDIChild.WindowState = FormWindowState.Maximized
End If
End Sub
Usage:
Public Sub Foo()
OpenForms(Of fDeliveryNotation)()
''OpenForms(Of Application)() Compile Error since Application is not a Form
End Sub
EDIT:
Added constructor constraint for T and create new instance of T instead of hard coded Form

Related

Pass Variable to NEW Form vs. OPEN Form

I have a WinForm that I want to pass a variable to. This form may or may not already be open. The code I was using would check to see if the form was open (using an IsOpen function) and then do a .BringToFront if it was open, or it would do a .Show if it was not open.
Now with trying to use New() to pass the variable, things are not working as expected. Creating the form variable, using Dim AdBook As New frmAddressBook, means a new instance of the form is created. When I run the IsOpen function, it does see the form. However, since I created a "new" form, when I run the AdBook.FillPatientInfo function of that form, the other variables have not been set up because that "new" form has not actually been loaded.
The only solution I have found thus far is to close the form and then open it again. But that sounds like more overhead than it should be. And besides, I'm not sure how I would close a form that I can't get a hold of.
Form 1 Click Event:
Private Sub tsmiAddressBook_Click(sender As Object, e As EventArgs) Handles tsmiAddressBook.Click
If IsDBNull(dgvPhysician.CurrentRow.Cells(1).Value) Then Exit Sub
Dim AdBook As New frmAddressBook(CInt(dgvPhysician.CurrentRow.Cells(1).Value))
If IsOpen(AdBook, Reflection.MethodBase.GetCurrentMethod().Name) Then
AdBook.BringToFront()
AdBook.FillPatientInfo(CInt(dgvPhysician.CurrentRow.Cells(1).Value))
Else
AdBook.Show(Me)
End If
End Sub
Form 2 New() code:
Private intID As Integer = Nothing
Public Sub New(ByVal newID As Integer)
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
intID = newID
End Sub
Code that checks to see if form IsOpen:
Public Function IsOpen(ByVal frm As Form, SubName As String) As Boolean
Try
Dim frmCol As New FormCollection()
frmCol = Application.OpenForms
Dim Cnt As Integer = 0
For Each f As Form In frmCol
If f.Name = frm.Name Then Cnt += 1
Next
Return CBool(IIf(Cnt > 0, True, False))
Catch ex As Exception
CustExErrorMsg("Functions", Reflection.MethodBase.GetCurrentMethod().Name, ex.Message)
Return False
End Try
End Function

Visual Studio - General Purpose Handler

I have a few menu items in my project that open new forms when clicked and every time I click on one I run the code below. However I have to add it for each MenuItem_Click event, so whenever I change the code I have to copy and past between forms. FormName is the only thing that changes. All of my menu items are named after the corresponding form, mi_FormName. And I know how to make a general event handler.
Is there any way to make it grab the name of the clicked on menu item, remove the mi_, and insert it in the same places as FormName?
Private Sub MenuItem_Click(sender As Object, e As EventArgs) Handles MenuItem.Click
Dim F As Form
If Not IsNothing(modForms.CheckOpen("FormName")) Then
F = modForms.CheckOpen("FormName")
If F.IsDisposed Then
modForms.CheckOpen.Remove("FormName")
F = New FormName
F.Show()
ElseIf F.Visible = False Then
F.Show()
Else
F.BringToFront()
End If
Else
F = New FormName
F.Show()
End If
End Sub
Why not just use a lambda that passes along the type of the form? You can use GetType to find the textual name and use a simple constraint to allow instances to be created
AddHandler mi_FormName.Click, Sub(s, e) OnClick(Of FormName)
AddHandler mi_OtherForm.Click, Sub(s, e) OnClick(Of OtherForm)
The click handler would look essentially as follows
Private Sub OnClick(Of T As {New, Form})()
Dim name = GetType(T).Name
Dim F As Form
If Not IsNothing(modForms.CheckOpen(name)) Then
F = modForms.CheckOpen(name)
If F.IsDisposed Then
modForms.CheckOpen.Remove(name)
F = New T
F.Show()
ElseIf F.Visible = False Then
F.Show()
Else
F.BringToFront()
End If
Else
F = New T
F.Show()
End If
End Sub

Show single instance of form in other project

I have multiproject solution where one project is "main", startup project.
From this project I starting forms in other projects which all are referenced in startup project.
Problem is that I can start those forms as instances like this:
Dim ka As New otherproject.frm_thatform
With ka
.BringToFront()
.Show(Me)
End With
That opens new "thatform" every time but I would like to to start "thatform" like single instance every time and that "thatform" comes to front.
How to do that?
I try like this:
Dim ka As otherproject.frm_thatform
With ka
.BringToFront()
.Show(Me)
End With
... but that don't work (Object reference not set to an instance of an object).
The trick is to not Dim the form and use it as a Shared object.
Otherproject.frm_thatform.Show()
Otherproject.frm_thatform.BringToFront()
As long as you dont close this window you can call it the same way as a Dimmed object.
Instead of ka you just type Otherproject.frm_thatform
As soon as you close the window it will loose everything in it.
EDIT: Apparently this only works with forms inside the project. My bad :(
What you need to do instead is keep a list of Forms inside your main project.
Make sure you give the form a name, and when you click the button to open the form simply loop through the list to find the set name.
Something like this:
Private FormList As New List(Of Form)
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
Dim theForm As Form = Nothing
For Each f As Form In FormList
If f.Name = "Selected form name" Then
theForm = f
End If
Next
If theForm Is Nothing Then
theForm = New Otherproject.frm_thatform()
theForm.Name = "Selected form name"
FormList.Add(theForm)
End If
End Sub
A couple of options -
create a static/ shared form variable
Shared form As SingletonformEx.Form1
If form IsNot Nothing Then
form.BringToFront()
Else
form = New SingletonformEx.Form1()
form.Show()
End If
Extend the form class and implement singleton pattern on it.
Public Class SingletonForm Inherits Form
Private Shared m_instance As SingletonForm
Private Sub New()
'InitializeComponent();
End Sub
Public Shared ReadOnly Property Instance() As SingletonForm
Get
If m_instance Is Nothing Then
m_instance = New SingletonForm()
End If
m_instance.BringToFront()
Return m_instance
End Get
End Property
End Class
note: this is C# code converted to vb.net so i am not sure if this is perfect
In your original code, move the form declaration out to class (form) level:
Private ka As otherproject.frm_thatform = Nothing
Then check to see if it is Nothing or has been disposed, and recreate it as necessary:
If (ka Is Nothing) OrElse ka.IsDisposed Then
ka = New otherproject.frm_thatform
ka.Show(Me)
End If
If ka.WindowState = FormWindowState.Minimized Then
ka.WindowState = FormWindowState.Normal
End If
ka.BringToFront()

Check if form is Opened

I give this question for more knowledge. How can I know if the form is Opened in my application or not, in order not to open it again I mean not to create an instance of the same form while it's running
Dim frmCollection As New FormCollection()
frmCollection = Application.OpenForms()
If frmCollection.Item("Form2").IsHandleCreated Then
MsgBox("Yes Opened")
Else
Dim f As New Form2()
With f
.Text = "form2"
.Show()
End With
End If
if I executes this code many times it will create more instances of the form Form2
How can I check if this form is not already opened
You can try it like this:
Imports System.Linq ' need to add
If Application.OpenForms().OfType(Of Form2).Any Then
MessageBox.Show("Opened")
Else
Dim f2 As New Form2
f2.Text = "form2"
f2.Show()
End If
You can use the following code:
If myForm.IsHandleCreated then
myForm is open
End If
As an extension of the answers given (thank you, all), here's a simple way to activate or show:
Dim frmCollection = System.Windows.Forms.Application.OpenForms
If frmCollection.OfType(Of Form2).Any Then
frmCollection.Item("Form2").Activate()
Else
Dim newForm2 = New Form2
newForm2.Show()
End If
For more simplicity you may create a public static bool variable which will tell whether the form is opened or not. On form load event assign 'true' and on closed event assign 'false' value.
ANOTHER refactoring way from the one initiated by HumbleBeginnings:
Dim xChildWindows = Application.OpenForms.OfType(Of frmForm2)
If xChildWindows.Any Then
xChildWindows.First().Focus() 'Focus if exists
Else
Dim xfrmNew As New frmForm2() 'Open window if doeasn't exists
xfrmNew.MdiParent = Me
xfrmNew.Show()
End If
Hate to be a kill joy but some day some one is going to try and understand your code.
Dim frm as New frmDontknow
Dim frmCollection = System.Windows.Forms.Application.OpenForms
For i As Int16 = 0I To frmCollection.Count - 1I
If frmCollection.Item(i).Name = frm.Name Then
frmCollection.Item(i).Activate()
Exit Sub
End If
Next i
Then do the show etc as required?
Check if form is Opened, To validate if a form is open we use this method and function to be able to invoke from any form and use less code.
Example :
This will use it in a form with mdiContainer and a panel object with 3 buttons that shows the 3 windows form.
Imports System
Imports System.Reflection
Private Sub OpenWindowsForm(ByVal FormName As String)
Dim instForm As Form = Application.OpenForms.OfType(Of Form)().Where(Function(frm) frm.Name = FormName).SingleOrDefault()
If instForm Is Nothing Then
Dim frm As New Form
frm = DirectCast(CreateObjectInstance(FormName), Form)
frm.MdiParent = Me
Me.Panel1.Controls.Add(frm)
Me.Panel1.Tag = frm
frm.Show()
Else
instForm.Select()
instForm.WindowState = FormWindowState.Maximized
instForm.BringToFront()
End If
End Sub
Public Function CreateObjectInstance(ByVal objectName As String) As Object
Dim obj As Object
Try
If objectName.LastIndexOf(".") = -1 Then
objectName = [Assembly].GetEntryAssembly.GetName.Name & "." & objectName
End If
obj = [Assembly].GetEntryAssembly.CreateInstance(objectName)
Catch ex As Exception
obj = Nothing
End Try
Return obj
End Function
How to use in click events
Private Sub btnRegistro_Click(sender As Object, e As EventArgs) Handles btnRegistro.Click
OpenWindowsForm("Registro")
End Sub
Private Sub btnBusqueda_Click(sender As Object, e As EventArgs) Handles btnBusqueda.Click
OpenWindowsForm("Busqueda")
End Sub
Private Sub btnCalendario_Click_1(sender As Object, e As EventArgs) Handles btnCalendario.Click
OpenWindowsForm("Calendario")
End Sub
Here is an image of the Sample code
you can try this
Dim formText As String
Dim prevText As String
Private Sub OpenForm(ByVal frm As Windows.Forms.Form)
formText = frm.Text
If formText = prevText Then Exit Sub
CloseForms()
' Make it a child of this MDI form before showing it.
frm.MdiParent = Me
frm.Show()
frm.Location = New Point(0, 0)
prevText = formText
End Sub
Private Sub CloseForms()
For Each ChildForm As Form In Me.MdiChildren
ChildForm.Close()
Next
End Sub
Private Sub NewToolStripButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PayablesToolStripMenuItem.Click
OpenForm(frmPayables)
End Sub
For Each frm As Form In Application.OpenForms
If frm.Name = Form1.Name Then
MessageBox.Show("Opened")
End If
Next

Calling external user control by its name

I have one panel (Panel1), two combo boxes (ComboBox1, ComboBox2) and one button (Button1) all in same form (Form1).
When the button is clicked:
Private Sub Button1_Click(sender As Object, e As EventArgs)
Dim a as String = ComboBox1.SelectedValue() & Combobox2.SelectedValue()
AddUserControl(a)
End Sub
value of a is the name of an external user control for instance p1k1.
Can I add an external user control named p1k1 to Panel1 in Form1 using following method?
Private Sub AddUserControl(ByVal a As String)
Panel1.Controls.Add(a)
End Sub
What should I do to make this work?
Usually I would use:
Panel1.Controls.Add(new p1k1)
You'll need to use reflection to do this. Something like this:
Private Sub AddUserControl(ByVal a As String)
Dim controlType As Type = Type.GetType(a)
If controlType Is Nothing Then
Throw New ArgumentException(String.Format("""{0}"" is not a valid type. Type names are case sensitive.", a))
ElseIf Not controlType.IsSubclassOf(GetType(Control)) Then
Throw New ArgumentException(String.Format("""{0}"" does not inherit from Control. Only Controls can be added to the control collection.", a))
End If
Dim newControl As Control = Activator.CreateInstance(controlType)
If newControl Is Nothing Then
Throw New ArgumentException(String.Format("Unspecified error when creating control of type ""{0}"".", a))
End If
Panel1.Controls.Add(newControl)
End Sub
i found my answer finally...
Private Sub AddUserControl(ByVal a As String)
Dim nmspace As String = "mynamespace"
Dim t As Type = Assembly.GetExecutingAssembly().GetType(nmspace & "." & a)
Dim o As Control = Activator.CreateInstance(t)
Panel1.Controls.Add(o)
End Sub