Calling external user control by its name - vb.net

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

Related

How to Convert string to Generic Of T?

How I call generic Of T sub choose form string?
How to better way code like this?
Sub ShowAddfrm(Of T As {Form, New})()
dim frm as new T 'New Form
frm.Show()
End Sub
Private Sub btnAddProblemfrm_Click(sender As Object, e As EventArgs)
Dim keys As String = CType(sender, Button).Name.Replace("btnAdd", "")
If keys = "frmShowProblem" Then
ShowAddfrm(Of frmShowProblem)()
End If
If keys = "frmUser" Then
ShowAddfrm(Of frmUser)()
End If
End Sub
Try this overloaded method, allowing both a Form reference and string parameter.
You can pass the default instance of a Form, naming it directly:
ShowAddfrm(Form2)
or the Form's name:
ShowAddfrm("Form2")
or using a Control's Tag property (or any other source) in an event handler:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
ShowAddfrm(DirectCast(sender, Control).Tag.ToString())
End Sub
There's a difference:
if you use pass the instance of a Form, only that instance will be created. Meaning, if you use a Button to show the Form and you press the Button multiple times, no new instances will be created. If you close the Form, then a new instance will be shown.
If you use the string version, each time you call this method, a new instance of the Form will be shown, so you can have multiple Forms on screen.
The string version uses Activator.CreateInstance to generate a new instance of a Form using it's name.
Sub ShowAddfrm(Of T As {Form, New})(ByVal form As T)
form.Show()
End Sub
Sub ShowAddfrm(formName As String)
Dim appNameSpace = Assembly.GetExecutingAssembly().GetName().Name
Dim form = CType(Activator.CreateInstance(Type.GetType($"{appNameSpace}.{formName}")), Form)
ShowAddfrm(form)
End Sub

Loop over controls in another class

I have created one form with two datagridviews, two text boxes with some random text, and two combo boxes with some random text.
I have created two classes. DataGridViewForm and DataGridViewClass
I loop over the controls on the DataGridViewForm to clear the controls
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' Pressing this button will clear all text and comboboxes
Dim button As New DataGridViewClass()
Dim a As Control = Nothing
For Each a In Me.Controls
button.Wissen = a
Next
End Sub
and it the DataGridViewClass
Property Wissen() As Control
Get
Return ControlName
End Get
Set(value As Control)
ControlName = value
If TypeOf ControlName Is TextBox Then
ControlName.Text = Nothing
ElseIf TypeOf ControlName Is ComboBox
ControlName.Text = String.Empty
End If
End Set
End Property
This works fine, but I would like to move the loop from the dgvFrom to the dgvClass. How would I do that? If I would move that loop I get the error "Controls is not a member of DataGridViewClass"
Okay, on the suggestion I tried this:
ControlName = value
Dim a As Control
For Each a In ControlName.Controls
If TypeOf a Is TextBox Then
a.Text = Nothing
ElseIf TypeOf a Is ComboBox
a.Text = String.Empty
End If
Next
And in DataGridViewForm I put
Dim button As New DataGridViewClass()
button.Wissen = Me
This works! Now I can use the same Clear button for other forms. Thanks!
The controls of DataGridViewForm are not static, you need to pass an instance of DataGridViewForm to an instance of DataGridViewClass and then DataGridViewClass will have access to all controls of DataGridViewForm, here is a basic example:
Public Class DataGridViewForm
Private DgvClassObj As DataGridViewClass
Sub New()
' pass this DataGridViewForm instance (Me) to an instance of DataGridViewClass
Init()
End Sub
Private Sub Init()
DgvClassObj = New DataGridViewClass(Me)
DgvClassObj.SomeMethodToLoopOverDataGridViewFormControls()
End Sub
End Class
Class DataGridViewClass
Private DgFormObj As DataGridViewForm
Sub New(ByRef dgform As DataGridViewForm)
Me.DgFormObj = dgform
End Sub
Public Sub SomeMethodToLoopOverDataGridViewFormControls()
For Each c As Control In DgFormObj.Controls
' now you can loop over the instance of your DataGridViewForm class
Next
End Sub
End Class

Cannot set focus to textbox

I am using VB and trying to select a portion of the text in a textbox of a separate form. However, I can't seem to find a good way to access the textbox from the other form, although the textbox is public (I am new to VB).
Currently, I'm trying to do this by calling a function located in the form (the form with the textbox), and then focusing on the textbox and selecting/highlighting the text. But it still doesn't work:
Public Sub GetFindLoc(ByVal lngStart As Long, ByVal intLen As Integer)
frmFind.Hide()
MessageBox.Show(ActiveForm.Name)
MessageBox.Show(txtNotes.CanFocus())
txtNotes.Focus()
txtNotes.Select(lngStart, intLen)
frmFind.Show()
End Sub
With this, I first hide the original form, and then try to select the text, and bring back the form. It shows that the active form is the one which I'm trying to select the text on, but it returns false on CanFocus().
Any help would be appreciated, thank you!
Hmm. This was more fiddly than I thought. You need to pass a reference to the other form:
Main form:
Public Class frmNotes
'This is the main form
'This form has a textbox named txtNotes and a button called btnShowFind
'txtNotes has .MultiLine=True
Private mfrmFind As frmFind
Private Sub btnShowFind_Click(sender As Object, e As EventArgs) Handles btnShowFind.Click
If mfrmFind Is Nothing OrElse mfrmFind.IsDisposed Then
mfrmFind = New frmFind(Me)
mfrmFind.Show()
Else
mfrmFind.BringToFront()
End If
End Sub
End Class
Finder form:
Public Class frmFind
'This form has a textbox called txtFind and a button called btnFind
Private mfrmParent As frmNotes
Sub New(parent As frmNotes)
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
mfrmParent = parent
End Sub
Private Sub btnFind_Click(sender As Object, e As EventArgs) Handles btnFind.Click
If txtFind.Text = "" Then
MsgBox("Please enter text to find", MsgBoxStyle.Exclamation)
Exit Sub
End If
Dim intSearchBegin As Integer = mfrmParent.txtNotes.SelectionStart + 1
Dim intStart As Integer = mfrmParent.txtNotes.Text.IndexOf(txtFind.Text, intSearchBegin)
If intStart > -1 Then
mfrmParent.txtNotes.Select(intStart, txtFind.Text.Length)
mfrmParent.txtNotes.Focus()
mfrmParent.BringToFront()
Else
mfrmParent.txtNotes.Select(0, 0)
MsgBox("No more matches")
End If
End Sub
End Class
Public Class frmFind
Private Sub btnFind_Click(sender As Object, e As EventArgs) Handles btnFind.Click
Dim search As String = TextBox1.Text.Trim
Dim pos As Integer = frmNotes.txtNotes.Text.IndexOf(search)
If pos > 0 Then
frmNotes.txtNotes.Focus()
frmNotes.txtNotes.Select(pos, search.Length)
End If
End Sub
End Class
This is just a "find" form with 1 textbox and 1 button which will highlight the first occurrence of the string in TextBox1 that it finds in txtNotes on the other form. If you want it to find whitespace as well, then remove the Trim function. You can add code to find other occurrences or go forward/backward.

How to get values from a dialog form in VB.NET?

I have a "frmOptions" form with a textbox named "txtMyTextValue" and a button named "btnSave" to save and close the form when it's clicked,
then, I'm showing this dialog form "frmOptions" when a button "btnOptions" is clicked on the main form "frmMain", like this
Private Sub btnOptions_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOptions.Click
ShowOptionsForm()
End Sub
Private Sub ShowOptionsForm()
Dim options = New frmOptions
options.ShowDialog()
End Sub
How can I get in the main form "frmMain" the value inserted in the textbox "txtMyTextValue" when the "btnSave" is clicked?
You want to capture the information from the dialog only if the result is OK (user presses Save instead of Cancel or closes the dialog some other way), so do this:
Private Sub ShowOptionsForm()
Dim options = New frmOptions
' Did the user click Save?
If options.ShowDialog() = Windows.Forms.DialogResult.OK Then
' Yes, so grab the values you want from the dialog here
Dim textBoxValue As String = options.txtMyTextValue.Text
End If
End Sub
Now inside of your dialog form, you need to set the result Windows.Forms.DialogResult.OK when the user clicks the button that corresponds to the OK action of the dialog form, like this:
Public Class frmOptions
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
' Set the result to pass back to the form that called this dialog
Me.DialogResult = Windows.Forms.DialogResult.OK
End Sub
End Class
The simplest method is to add a public property to the frmOptions form that returns an internal string declared at the global level of the frmOptions
Dim strValue As String
Public Property MyStringValue() As String
Get
Return strValue
End Get
End Property
Then, when your user clicks the OK button to confirm its choices you copy the value of the textbox to the internal variable
Private Sub cmdOK_Click(sender As Object, e As System.EventArgs) Handles cmdOK.Click
strValue = txtMyTextValue.Text
End Sub
Finally in the frmMain you use code like this to retrieve the inserted value
Private Sub ShowOptionsForm()
Using options = New frmOptions()
if DialogResult.OK = options.ShowDialog() Then
Dim value = options.MyStringValue
End If
End Using
End Sub
I prefer to avoid direct access to the internal controls of the frmOptions, a property offer a indirection that could be used to better validate the inputs given by your user.
You can use Events to take care of this. With this approach the Settings Form does not have to be Modal and the user can click the Save Button at any time.
In frmOptions:
'You can expand the signature to take more than just a single String.
Friend Event SavedOptions(ByVal strData As String)
Private Sub btnSave_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSave.Click
RaiseEvent SavedOptions(txtMyTextValue.Text)
End Sub
In frmMain:
Private Sub ShowOptionsForm()
Dim options = New frmOptions
AddHandler options.SavedOptions, AddressOf OnOptionsSave
options.ShowDialog()
End Sub
Private Sub OnOptionsSave(ByVal strData As String)
'Or whatever you want to do on frmMain with Options Data.
MsgBox(strData)
End Sub
You can access the value from the frmOptions instance. However, this breaks the law of demeter.
You should expose the value with a property within your class.
Public Class frmOptions
Public ReadOnly Property MyTextValue As String
Get
Return Me.txtMyTextValue.Text
End Get
End Property
End Class
Then you can access the value:
Private Sub ShowOptionsForm()
Dim options = New frmOptions
Dim frmOptionTextValue As String
Dim frmOptionsDiagResult As DialogResult
frmOptionsDiagResult = options.ShowDialog()
If frmOptionsDiagResult = Windows.Forms.DialogResult.OK Then
frmOptionTextValue = options.MyTextValue
Else
'...
End If
End Sub
Finally, if you are using a Dialog then make sure to set the Dialog Result for the button.

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