VB.NET Me.Close() doesn't work, the form doesn't close? - vb.net

The form is an About Us form so has nothing on it only a text box and a OK button.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Me.Close()
End Sub
Here is how I'm opening the form:
Private Sub AboutAppStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AboutAppStripMenuItem.Click
Dim formAbout As New FormAbout()
formAbout.Show()
End Sub
Why won't the button close the form? I'm puzzled, I tried another button just in case with the same result.
UPDATE: I set a break point on Me.Close() and it isn't reaching it when I click the button, I created a new button and the same thing happened.
Thanks

I am betting the event handler for the button1_click event has been inadvertently removed.
Try double-clicking on the button in design time and see if it pulls you back to that same exact piece of code - or a new event handler definition.
If it's a new event handler definition - copy your code there and delete the first one.
There are other ways to manually add the event handler in the designer's code-behind - but maybe that's for a later progression.
From within VS click the "Show all files" button in solutions explorer. Grab us the code in .Designer.vb and paste it in here and we'll nail it down for you definitively.
Here's mine:
Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
_
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
_
Private Sub InitializeComponent()
Me.Button1 = New System.Windows.Forms.Button
Me.SuspendLayout()
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(131, 91)
Me.Button1.Name = "Button1"
Me.Button1.Size = New System.Drawing.Size(133, 50)
Me.Button1.TabIndex = 0
Me.Button1.Text = "Button1"
Me.Button1.UseVisualStyleBackColor = True
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(292, 266)
Me.Controls.Add(Me.Button1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
End Sub
Friend WithEvents Button1 As System.Windows.Forms.Button
End Class

From MSDN:
Showing the control is equivalent to setting the Visible property to true. After the Show method is called, the Visible property returns a value of true until the Hide method is called.

when formabout is open
click on pause(break all) button in visual studio
click on step into in debug in visual studio
click on the close button in formabout
you will see which code is executed, if any
* edit *
another question
is formabout.enabled property is true?

I tested the following
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Dim f As New Form2
f.Show()
End Sub
End Class
Public Class Form2
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Me.Close()
End Sub
End Class
and did not have problems. As was suggested, re-create your button and code.

Add you Button Dynamically may solve the problem.
Place the following code in the load event of about Form.
Public Sub FormAbout_Load(ByVal sender as object,ByVal e as System.EventArgs)Handles Me.Load
Dim btn as new Button()
AddHandler btn.Click ,AddressOf _ClickToClose
End Sub
Private Sub _ClickToClose(ByVal sender as object,ByVal e as System.EventArgs)
Me.Close()
End Sub

Simple.
Select Project Properties from Solution Explorer.
Select Security tab to either uncheck "Enable ClickOnce..." or select "This is a full trust application".
Save the properties settings.
Solved.

Related

Send data within Child Forms

I have 3 Forms namely MainForm, Form1 and Form2. MainForm hosts Form1 in a Panel. On Clicking a button in MainForm, I am opening Form2 using ShowDialog() method. Now I have a treeview in Form2. Now I want to pass the nodes selected in Form2 back to a combobox in Form1. How can this be achieved? I have tried Form1.Activate() in Form2 but the code is not hitting Activate method in Form1.
Also I am using Form1.ComboBox1.Items.Add(Me.TreeView1.SelectedNode.Text) but I cannot see any items in ComboBox once Form2 is closed. What am I missing here?
Below is the code for better understanding.
MainForm
public Class MainForm
private Sub OpenChildForm(childForm As Form)
panelFormContainer.Controls.Add(childForm)
childForm.Dock = DockStyle.Fill
childForm.Show()
End Sub
private sub MainForm_OnLoad(sender As Object, e as EventArgs) Handles Me.Load
'Adding child form to a Panel in Main Form
OpenChildForm(new Form1())
End Sub
'Open Form 2 on Button Click
private sub btnOpenForm3_Click(sender As Object, e as EventArgs) Handles btnOpenForm3.Click
Form2.ShowDialog()
End Sub
End Class
Form2 - Child Form Opened by button click in MainForm
Public Class Form2
'Click back button to go back to Main Form which is already having Form1 as child
Private Sub btnBack_Click(sender As Object, e As EventArgs)
Me.Close()
Form1.Activate()
End Sub
'Click a Button to Add Selected Treeview node to Combo in Form1
Private Sub btnAdd_Click(sender As Object, e As EventArgs) btnAdd.Click
Form1.ComboBox1.Items.Add(Me.TreeView1.SelectedNode.Text)
End Sub
End Class
Updated: I have updated the code but still not getting anything in ComboBox of Child Form1
MainForm
Public Class Form1
Private currentChildForm As Form = Nothing
Private ownerForm As Form = Nothing
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
OpenChildForm(New ChildForm1())
End Sub
Private Sub OpenChildForm(childForm As Form)
If currentChildForm IsNot Nothing Then
currentChildForm.Close()
End If
childForm.TopLevel = False
childForm.FormBorderStyle = FormBorderStyle.None
panelFormContainer.Controls.Clear()
panelFormContainer.Controls.Add(childForm)
childForm.Dock = DockStyle.Fill
childForm.BringToFront()
childForm.Show()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim dialogForm As ChildForm2 = New ChildForm2()
'
Dim result = dialogForm.ShowDialog()
If result = DialogResult.OK Then
AddHandler ChildForm2.Button1.Click, AddressOf ChildForm1.objForm2_Passvalue
End If
End Sub
End Class
ChildForm1 which is hosted in MainForm
Public Class ChildForm1
Private Sub ChildForm1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
If ComboBox1.Items.Count > 0 Then
ComboBox1.SelectedIndex = 0
End If
End Sub
Private Sub ChildForm1_Activated(sender As Object, e As EventArgs) Handles Me.Activated
End Sub
Public Sub objForm2_Passvalue(sender As Object, e As EventArgs)
Me.ComboBox1.Items.Add(PageDetail.PageTitle)
End Sub
End Class
ChildForm2 -- Which is opened as Dialog
Public Class ChildForm2
Private Sub ChildForm2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
TreeView1.ExpandAll()
Button1.DialogResult = DialogResult.OK
End Sub
Public Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
PageDetail.PageTitle = TreeView1.SelectedNode.Text
Me.Close()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Me.Close()
End Sub
End Class
PageDetail: Class used to get and set data
Public NotInheritable Class PageDetail
Private Shared pageTitleValue As String
Public Shared Property PageTitle As String
Get
Return pageTitleValue
End Get
Set(value As String)
pageTitleValue = value
End Set
End Property
End Class
The following shows multiple ways to pass data between forms. In the code below, I show how to retrieve data from a child form (ChildForm2) using a function, a property, or an event. This data is passed back to the parent form (MainForm). Once the parent form (MainForm) receives the data, it sends the data to a different child form (ChildForm1). Data can be sent from the parent form (MainForm) to the child form (ChildForm1) using one of the constructors, a method, or a property.
Note: MainForm is the startup form and is the parent to both ChildForm1 and ChildForm2 (ie: instances of both ChildForm1 and ChildForm2 are created in MainForm)
Create a new project
VS 2019:
In VS menu, click File
Select New
Select Project
Select Windows Forms App (.NET Framework)
Click Next
Enter desired project name
Click Create
Open Solution Explorer
In VS menu, select View
Select Solution Explorer
Add Form (Name: ChildForm1.vb)
In Solution Explorer, right-click <project name>, select Add
Select Form (Windows Forms)... (name: ChildForm1.vb)
Add a Label (Text: "Select One")
Add a ComboBox (Name: ComboBox1)
In Solution Explorer, right click ChildForm1.vb, and select View Code
ChildForm1.vb
Public Class ChildForm1
Public WriteOnly Property PageTitle As String
Set(value As String)
'populate ComboBox
PopulateComboBox(value)
End Set
End Property
Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
End Sub
Sub New(pageTitle As String)
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
PopulateComboBox(pageTitle)
End Sub
Sub New(pageTitles As List(Of String))
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
PopulateComboBox(pageTitles)
End Sub
Private Sub ChildForm1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Public Sub PopulateComboBox(pageTitle As String)
'create new instance
Dim pageTitles As New List(Of String)
'add
pageTitles.Add(pageTitle)
'populate ComboBox
PopulateComboBox(pageTitles)
End Sub
Public Sub PopulateComboBox(pageTitles As List(Of String))
'remove existing data from ComboBox
ComboBox1.Items.Clear()
ComboBox1.Text = String.Empty
For Each pTitle In pageTitles
'add
ComboBox1.Items.Add(pTitle)
Next
If ComboBox1.Items.Count = 1 Then
'if only 1 item exists, select it
ComboBox1.SelectedIndex = 0
End If
End Sub
End Class
Add a Form (name: ChildForm2.vb)
In Solution Explorer, right-click <project name>, select Add
Select Form (Windows Forms)... (Name: ChildForm2.vb)
Add a Label
Add a TreeView (name: TreeView1)
Add a Button (Name: btnAdd; Text: Add)
Double-click "btnAdd" to add the Click event handler
Add a Button (Name: btnCancel; Text: Cancel)
Double-click "btnCancel" to add the Click event handler
In Solution Explorer, right click ChildForm2.vb, and select View Code
ChildForm2.vb
Public Delegate Sub PassValueHandler(ByVal strValue As String)
Public Class ChildForm2
Public Event PassValue As PassValueHandler
Public ReadOnly Property PageTitle
Get
Return TreeView1.SelectedNode.Text
End Get
End Property
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
PopulateTreeView()
TreeView1.ExpandAll()
End Sub
Public Function GetPageTitle() As String
Return PageTitle
End Function
Private Sub PopulateTreeView()
'ToDo: Replace this method with code to populate your TreeView
TreeView1.Nodes.Clear()
'Parent 1
Dim node1 As TreeNode = New TreeNode("Parent 1")
Dim childNode1 As TreeNode = New TreeNode("Child Node 1")
'add
node1.Nodes.Add(childNode1)
'add
TreeView1.Nodes.Add(node1)
'Parent 2
Dim node2 As TreeNode = New TreeNode("Parent 2")
Dim childNode2 As TreeNode = New TreeNode("Child Node 2")
'add
node2.Nodes.Add(childNode2)
'add
TreeView1.Nodes.Add(node2)
End Sub
Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
'raise event
RaiseEvent PassValue(TreeView1.SelectedNode.Text)
'set value
Me.DialogResult = DialogResult.OK
'close
Me.Close()
End Sub
Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
'set value
Me.DialogResult = DialogResult.Cancel
'close
Me.Close()
End Sub
End Class
Rename Form1 to MainForm
In Solution Explorer, right-click Form1.vb
Select Rename
Enter MainForm.vb
When prompted "You are renaming a file. Would you also like to perform a rename in this project of all references to the code element 'Form1'? Click Yes
In Properties Window, for "MainForm", set Text = "MainForm"
MainForm
Add a panel to MainForm (Name: panelFormContainer)
Add Button (Name: btnOpenChildForm2; Text: Open ChildForm2)
Double-click "btnOpenChildForm2" to add the Click event handler
In Solution Explorer, right click MainForm.vb, and select View Code
In the code below, I've written it in such a way that it allows one to choose different options for both retrieving data from a child form, as well as, multiple options for sending data to a child form.
MainForm.vb
Public Class MainForm
Private dialogForm As ChildForm2 = Nothing
Private currentChildForm As Form = Nothing
Private ownerForm As Form = Nothing
Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'open Form
OpenChildForm(New ChildForm1())
End Sub
Private Sub OpenChildForm(ByRef childForm As Form)
If currentChildForm IsNot Nothing Then
currentChildForm.Dispose()
currentChildForm = Nothing
End If
'set value
currentChildForm = childForm
'set properties
childForm.Dock = DockStyle.Fill
childForm.TopLevel = False
childForm.FormBorderStyle = FormBorderStyle.None
'remove existing controls
panelFormContainer.Controls.Clear()
'add
panelFormContainer.Controls.Add(childForm)
'show
childForm.Show()
End Sub
Private Sub PopulateChildForm1ComboBox(pageTitle As String)
If currentChildForm.GetType() = ChildForm1.GetType() Then
'currentChildForm is an instance of ChildForm1
'create reference
Dim frm = CType(currentChildForm, ChildForm1)
'option 1 - populate ComboBox by calling method
frm.PopulateComboBox(pageTitle)
'option 2 - populate ComboBox by setting property
'frm.PageTitle = PageDetail.PageTitle
End If
End Sub
Private Sub btnOpenChildForm2_Click(sender As Object, e As EventArgs) Handles btnOpenChildForm2.Click
'ToDo: Replace this method with code from Option 1, Option 2, or Option 3 below
...
End Sub
Private Sub DialogForm_BtnAdd_Click(sender As Object, e As System.EventArgs)
'option 1 - get page title from property
PageDetail.PageTitle = dialogForm.PageTitle
'option 2 - get page title by calling function
'PageDetail.PageTitle = dialogForm.GetPageTitle()
'populate ComboBox
PopulateChildForm1ComboBox(PageDetail.PageTitle)
End Sub
Private Sub DialogForm_PassValue(e As String)
'set value
PageDetail.PageTitle = e
'populate ComboBox
PopulateChildForm1ComboBox(e)
End Sub
End Class
Choose one of the following options for retrieving data from ChildForm2. Replace the method btnOpenChildForm2_Click (in MainForm.vb) with the code listed below.
Option 1 (DialogResult.OK)
Private Sub btnOpenChildForm2_Click(sender As Object, e As EventArgs) Handles btnOpenChildForm2.Click
'create new instance
dialogForm = New ChildForm2()
'show dialog
If dialogForm.ShowDialog() = DialogResult.OK Then
PageDetail.PageTitle = dialogForm.PageTitle
'populate ComboBox
PopulateChildForm1ComboBox(PageDetail.PageTitle)
End If
'dispose
dialogForm.Dispose()
dialogForm = Nothing
End Sub
Note: When using Option 1, the code for DialogForm_BtnAdd_Click and DialogForm_PassValue (in MainForm.vb) isn't used, so both of these methods can be removed.
Option 2 (subscribe to btnAdd 'Click' event)
Private Sub btnOpenChildForm2_Click(sender As Object, e As EventArgs) Handles btnOpenChildForm2.Click
'create new instance
dialogForm = New ChildForm2()
'subscribe to events (add event handlers)
AddHandler dialogForm.btnAdd.Click, AddressOf DialogForm_BtnAdd_Click
'show dialog
dialogForm.ShowDialog()
'unsubscribe from events (remove event handlers)
RemoveHandler dialogForm.btnAdd.Click, AddressOf DialogForm_BtnAdd_Click
'dispose
dialogForm.Dispose()
dialogForm = Nothing
End Sub
Note: When using Option 2, the code for DialogForm_PassValue (in MainForm.vb) isn't used, so method DialogForm_PassValue can be removed.
Option 3 (subscribe to event 'PassValue')
Private Sub btnOpenChildForm2_Click(sender As Object, e As EventArgs) Handles btnOpenChildForm2.Click
'create new instance
dialogForm = New ChildForm2()
'subscribe to events (add event handlers)
AddHandler dialogForm.PassValue, AddressOf DialogForm_PassValue
'show dialog
dialogForm.ShowDialog()
'unsubscribe from events (remove event handlers)
RemoveHandler dialogForm.PassValue, AddressOf DialogForm_PassValue
'dispose
dialogForm.Dispose()
dialogForm = Nothing
End Sub
Note: When using Option 3, the code for DialogForm_BtnAdd_Click (in MainForm.vb) isn't used, so method DialogForm_BtnAdd_Click can be removed.
Here's a demo:
Resources:
Form.ShowDialog
Form.Show
How to populate a treeview from a list of objects
Rather than placing a Form on a panel, you might consider creating a UserControl and placing that on the panel. The following show how to pass data from a Form (Form2) that is shown using ShowDialog() to a UserControl (UserControl1) that exists on a different form (MainForm).
Note: MainForm is the startup form. If desired, the UserControl can be replaced with a Form.
Create a new project
VS 2019:
In VS menu, click File
Select New
Select Project
Select Windows Forms App (.NET Framework)
Click Next
Enter desired project name
Click Create
Open Solution Explorer
In VS menu, select View
Select Solution Explorer
Add UserControl (Name: UserControl1.vb)
In Solution Explorer, right-click <project name>, select Add
Select User Control (Windows Forms)... (name: UserControl1.vb)
Add a Label (Text: "Select One")
Add a ComboBox (Name: ComboBox1)
UserControl1.vb
Public Class UserControl1
Private Sub UserControl1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Public Sub PopulateComboBox(value As String)
'remove existing data from ComboBox
ComboBox1.Items.Clear()
ComboBox1.Text = String.Empty
'add
ComboBox1.Items.Add(value)
If ComboBox1.Items.Count = 1 Then
'if only 1 item exists, select it
ComboBox1.SelectedIndex = 0
End If
End Sub
End Class
Note: If using a Form instead of a UserControl, add the code for PopulateComboBox to your form.
Add a Form (name: Form2.vb)
In Solution Explorer, right-click <project name>, select Add
Select Form (Windows Forms)... (Name: Form2.vb)
Add a Label
Add a TreeView (name: TreeView1)
Add a Button (Name: btnAdd; Text: Add)
Double-click "btnAdd" to add the Click event handler
Add a Button (Name: btnCancel; Text: Cancel)
Double-click "btnCancel" to add the Click event handler
In Solution Explorer, right click Form2.vb, and select View Code
Form2.vb
Imports System.IO
Public Class Form2
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
PopulateTreeView()
End Sub
'ToDo: Replace this function with one that returns the desired data
Public Function GetSelectedValue() As String
Return TreeView1.SelectedNode.Text
End Function
Private Sub PopulateTreeView()
'ToDo: Replace this code with your desired code to populate the TreeView
'clear
TreeView1.Nodes.Clear()
Dim topNode As TreeNode = New TreeNode("Computer")
TreeView1.Nodes.Add(topNode)
Dim logicalDrives As String() = Directory.GetLogicalDrives()
If logicalDrives IsNot Nothing Then
For Each drive As String In logicalDrives
Debug.WriteLine("drive: " & drive.ToString())
Try
Dim dirInfo As DirectoryInfo = New DirectoryInfo(drive)
TreeView1.Nodes.Add(New TreeNode(drive))
Catch ex As Exception
'do nothing
End Try
Next
End If
End Sub
Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
'in MainForm we'll subscribe to the Add button Click event and retrieve the data by calling function "GetSelectedValue", so all we have to do here is close the form
Me.Close()
End Sub
Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
Me.Close()
End Sub
End Class
Rename Form1 to MainForm
In Solution Explorer, right-click Form1.vb
Select Rename
Enter MainForm.vb
When prompted "You are renaming a file. Would you also like to perform a rename in this project of all references to the code element 'Form1'? Click Yes
In Properties Window, for "MainForm", set Text = "MainForm"
Build Project
In Solution Explorer, right-click <project name>, select Build
MainForm
Add a panel to MainForm (Name: panel1)
In Toolbox (View => Toolbox), expand: <solution name> Components
Drag UserControl1 onto panel1 on MainForm
Add Button (Name: btnOpenForm2; Text: Open Form2)
Double-click "btnOpenForm2" to add the Click event handler
In Solution Explorer, right click MainForm.vb, and select View Code
MainForm.vb
Public Class MainForm
Private frm2 As Form2 = Nothing
Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub btnOpenForm2_Click(sender As Object, e As EventArgs) Handles btnOpenForm2.Click
If frm2 Is Nothing Then
'create new instance
frm2 = New Form2()
End If
'subscribe to events (add event handlers)
AddHandler frm2.btnAdd.Click, AddressOf Frm2BtnAdd_Click
'show dialog
frm2.ShowDialog()
'the code below will execute after frm2 is closed
'unsubscribe from events (remove event handlers)
RemoveHandler frm2.btnAdd.Click, AddressOf Frm2BtnAdd_Click
'dispose
frm2.Dispose()
frm2 = Nothing
End Sub
Private Sub Frm2BtnAdd_Click(sender As Object, e As System.EventArgs)
'call method to populate ComboBox
'UserControl11.PopulateComboBox(frm2.GetSelectedValue())
'call function to get data
Dim userSelection As String = frm2.GetSelectedValue()
'call method to populate ComboBox
UserControl11.PopulateComboBox(userSelection)
End Sub
End Class
Here's a demonstration:
Resources
How to populate a treeview from a list of objects

how to add (gotfocus - lostfocus) events to all textbox in the project

I created a project one year ago and now I want to add background color to all the focused textboxes.
I know I can create the events for all textboxes but it will take a lot of time, and I know that I can create a custom control (textbox) but I don't prefer.
so can I add those events for all textboxes in my project?
Let's go through all the possibilities here.
Firstly, the usual thing to do with events is to create a distinct handler for each event of each control, e.g.
Private Sub TextBox1_Enter(sender As Object, e As EventArgs) Handles TextBox1.Enter
'...
End Sub
Private Sub TextBox1_Leave(sender As Object, e As EventArgs) Handles TextBox1.Leave
'...
End Sub
Private Sub TextBox2_Enter(sender As Object, e As EventArgs) Handles TextBox2.Enter
'...
End Sub
Private Sub TextBox2_Leave(sender As Object, e As EventArgs) Handles TextBox2.Leave
'...
End Sub
If you're doing the same thing for the same event of each control though, you can condense that into a single event handler per event:
Private Sub TextBoxes_Enter(sender As Object, e As EventArgs) Handles TextBox1.Enter, TextBox2.Enter
Dim tb = DirectCast(sender, TextBox)
'...
End Sub
Private Sub TextBoxws_Leave(sender As Object, e As EventArgs) Handles TextBox1.Leave, TextBox2.Leave
Dim tb = DirectCast(sender, TextBox)
'...
End Sub
The sender parameter refers to the object that raised the event, so you can access the appropriate TextBox with a cast. The objects whose event you handle don't have to be the same type and you can even handle multiple events with the one method, as long as the signatures are compatible:
Private Sub Controls_FocusChanged(sender As Object, e As EventArgs) Handles TextBox1.Enter,
TextBox2.Enter,
ComboBox1.Enter,
TextBox1.Leave,
TextBox2.Leave,
ComboBox1.Leave
Dim cntrl = DirectCast(sender, Control)
'The event is raised before the change happens so the control
'will have focus on Leave and will not have focus on Enter.
cntrl.BackColor = If(cntrl.Focused, SystemColors.Window, Color.Yellow)
End Sub
Note that the designer can help you do this. You can select multiple controls, open the Properties window, click the Events button and then double-click the desired event to generate a single event handler with the selected event for all selected controls in the Handles clause. You can then select that existing event handler in the drop-down list for another event for one or more controls to add then to the Handles clause too. You can edit the method name in the code window as appropriate. You can also write the method and the Handles clause yourself if you want to.
Secondly, to write less code in each form, you can put your event handler(s) in a module somewhere and then use the AddHandler statement to attach it to the events when a form loads:
Module CommonEventHandlers
Public Sub Controls_FocusChanged(sender As Object, e As EventArgs)
Dim cntrl = DirectCast(sender, Control)
'The control will have focus on Leave and will not have focus on Enter.
cntrl.BackColor = If(cntrl.Focused, SystemColors.Window, Color.Yellow)
End Sub
End Module
and:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For Each tb In Controls.OfType(Of TextBox)()
AddHandler tb.Enter, AddressOf CommonEventHandlers.Controls_FocusChanged
AddHandler tb.Leave, AddressOf CommonEventHandlers.Controls_FocusChanged
Next
End Sub
Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
For Each tb In Controls.OfType(Of TextBox)()
RemoveHandler tb.Enter, AddressOf CommonEventHandlers.Controls_FocusChanged
RemoveHandler tb.Leave, AddressOf CommonEventHandlers.Controls_FocusChanged
Next
End Sub
That will handle the events for all TextBoxes that were added directly to the form. If you want different controls and/or some are in child containers then you would need to adjust that accordingly. Note that the event handlers need to be removed when you're done.
Finally, the "proper" solution is to use a custom control. You create a custom control simply by adding a class to your project and then adding an Inherits line to that class. You then override the appropriate method for the event you would otherwise handle, e.g. OnEnter method for Enter event. The code you put in the method is basically the same as you would put in the event handler, except it refers to the current object rather than the sender:
Public Class TextBoxEx
Inherits TextBox
Private defaultBackColor As Color
''' <inheritdoc />
Protected Overrides Sub OnEnter(e As EventArgs)
defaultBackColor = BackColor
BackColor = Color.Yellow
MyBase.OnEnter(e)
End Sub
''' <inheritdoc />
Protected Overrides Sub OnLeave(e As EventArgs)
BackColor = defaultBackColor
MyBase.OnLeave(e)
End Sub
End Class
You can then just edit the designer code files of your existing forms to use that custom control instead of the standard TextBox, e.g. this:
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Me.TextBox1 = New System.Windows.Forms.TextBox()
Me.SuspendLayout()
'
'TextBox1
'
Me.TextBox1.Location = New System.Drawing.Point(0, 0)
Me.TextBox1.Name = "TextBox1"
Me.TextBox1.Size = New System.Drawing.Size(100, 20)
Me.TextBox1.TabIndex = 0
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(800, 450)
Me.Controls.Add(Me.TextBox1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Friend WithEvents TextBox1 As TextBox
becomes this:
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Me.TextBox1 = New TextBoxEx()
Me.SuspendLayout()
'
'TextBox1
'
Me.TextBox1.Location = New System.Drawing.Point(0, 0)
Me.TextBox1.Name = "TextBox1"
Me.TextBox1.Size = New System.Drawing.Size(100, 20)
Me.TextBox1.TabIndex = 0
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(800, 450)
Me.Controls.Add(Me.TextBox1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Friend WithEvents TextBox1 As TextBoxEx
That's just two lines of code changed per control, which you can do with the Find & Replace functionality. Everything will look and work exactly as it did before, but your TextBoxes will automatically exhibit the new behaviour. Once you've built your project, the custom control will be added to the Toolbox, so you can add it to forms in the designer like any other control.
Note that, in order to access the designer code files, you need to select your project or an item within it in the Solution Explorer and click the Show All Files button. You can then expand the node for your form and open the designer code file.

Changing Controls of a form inside a panel

I am facing a weird problem
I have 3 forms: MainForm, Form1, Form2
MainForm has 1 Panel: Panel1
Form1 has 1 Label: NameLbl and Button: ChangeBtn
Form2 has 1 textbox: NameTxt and Button: SaveBtn
I used the following code to open form1 inside Panel1 in mainform
Panel1.Controls.Clear()
Dim FormInPanel As New Form1()
FormInPanel.TopLevel = False
Panel1.Controls.Add(FormInPanel)
FormInPanel.Show()
On ChangeBtn.Click Form2 opens as showdialog
I want NameLbl.text to change to NameLbl.text when SaveBtn is clicked But normal code doesnt work.
Private Sub SaveBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveBtn.Click
Form1.NameLbl.text=NameTxt.text
End Sub
What Should I do? Any suggestions? Given that i need to open the forms in panels for certain reasons.
Please keep in mind that this is just an example. I have multiple controls in Form1 which i want to change on form2.SaveBtn.click
I have also tried this but it does nothing
Private Sub SaveBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveBtn.Click
For Each c As Control In MainForm.Panel1.Controls(0).Controls
If c.Name="NameLbl" Then
c.Text = NameTxt.Text
End If
Next
End Sub
Please Somebody tell me how it do it!
Form2 doesn't seem to have any connection back to Form1 or MainForm. You'd need to raise an event from Form2 which MainForm handles or another class handles and can pass to MainForm
Edit:
Sorry, I've just seen how you're calling Form2. There are lots of ways to get a value back from Form2 after calling ShowDialog(). One is to create a property called Result and check Result if ShowDialog() == DialogResult.OK. Something like the following.
Public Class Form2
Inherits System.Windows.Forms.Form
Public Property Result() As String
Get
Return m_Result
End Get
Set
m_Result = Value
End Set
End Property
Private m_Result As String
End Class
Public Class Form1
Inherits System.Windows.Forms.Form
Public ChangeBtn As Button
Public NameLbl As Label
Public Sub New()
Me.ChangeBtn = New Button()
AddHandler Me.ChangeBtn.Click, AddressOf ChangeBtn_Click
Me.NameLbl = New Label()
End Sub
Private Sub ChangeBtn_Click(sender As Object, e As EventArgs)
Dim form As New Form2()
Dim dr = New form.ShowDialog()
If dr = DialogResult.OK Then
Me.NameLbl.Text = form.Result
End If
End Sub
End Class
I'd like to add that if you plan on growing this application much larger you'll run into issues with maintenance. Look into some patterns for dealing with UI logic like MVC, MVP, MVVM if you're interested.
you can try this code:
Private Sub SaveBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveBtn.Click
panel1.Controls(0).NameLbl.text=NameTxt.text '"0" is the index of forminpanel in panel1,maybe it need to change.
End Sub
Form1 is contained in Panel1, so you can not access it via
Form1.
Only MainForm is visible from Form2:
Private Sub SaveBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveBtn.Click
For Each c As Control In MainForm.Panel1.Controls(0).Controls
If TypeOf c Is TextBox Then
c.Text = NameTxt.Text
End If
Next
End Sub
Try this:
For Each form1 As Form1 In MainForm.OwnedForms.OfType(Of Form1)
Form1.NameLbl.text = NameTxt.text
Next
I've faced same issue and I've fixed with this
Dim f As FormInPanel
f = Form.Panel1.Controls(0)
f.transection = True
f.NameLbl.text=NameTxt.text

.Net WindowsForms MouseDown event not firing

As a new user to VB, I am struggling to see why this code works in one project but not in another. This code works fine if I create a new project and 2 new forms but when I place in my project, it doesn't fire at all on either left or right click.
I have tried a try/catch statement, but no errors are being reported. How do I go about troubleshooting this to find out the error. I have tried to rem out code and run after each comment but still the same. I have even tried removing all other code on the form leaving just the 2 subs but no joy. Any help would be greatly appreciated.
frmMain
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'StorageDataSet1.Customers' table. You can move, or remove it, as needed.
Me.CustomersTableAdapter.Fill(Me.StorageDataSet1.Customers)
'TODO: This line of code loads data into the 'StorageDataSet.User' table. You can move, or remove it, as needed.
Me.UserTableAdapter.Fill(Me.StorageDataSet.User)
'Dim frmDepartmentsLive As New frmDepartment
'frmDepartmentsLive.Owner = Me
'frmDepartmentsLive.ShowDialog()
lblDate.Text = Now
Timer1.Start()
rdoCustomer.Enabled = False
rdoCustomer.Checked = True
rdoDepartment.Enabled = False
rdoDepartment.Checked = False
For Each ctrl In Me.Controls
If TypeOf ctrl Is Button Then
AddHandler CType(ctrl, Button).MouseDown, AddressOf btn_MouseDown
End If
Next
End Sub
Private Sub btn_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs)
If (e.Button = MouseButtons.Right) Then
Dim btn = CType(sender, Button)
frmRacks.buttonName = btn.Name.Replace("btn", "")
frmRacks.Show()
ElseIf (e.Button = MouseButtons.Left) Then
MessageBox.Show("To be coded")
End If
End Sub
frmRacks
Public Class frmRacks
Public buttonName As String
Private Sub racksfrm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
lblRacks.Text = buttonName
End Sub
Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
Me.Close()
End Sub
End Class
Since the controls are on a panel, they are members of that panel's controls array, not the form's. This -- and other things -- are apparent if you look thru the form's designer (on solution explorer, click Show All, then open formXXX.designer.vb). DOnt change anything, but it shows how controls are created and added. So...
For Each ctrl In thepanelName.Controls
If TypeOf ctrl Is Button Then
AddHandler CType(ctrl, Button).MouseDown, AddressOf btn_MouseDown
End If
Next
If it is ONLY those buttons on the panel you can short cut it:
For Each btn As Button In thepanelName.Controls
AddHandler CType(ctrl, Button).MouseDown, AddressOf btn_MouseDown
Next

Using handlers across multiple forms?

I have code that highlights the current textbox in focus in order to provide a visual cue to the user. My question is, if I had 10 forms with textboxes and I wanted to provide this same code to them all. Would I have to duplicate it or can I use a global method? If so, an example would be very helpful. Thanks.
The code is as follows.
Private Sub FocusChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim txt As TextBox = sender
If txt.Focused Then
txt.Tag = txt.BackColor
txt.BackColor = Color.AliceBlue
Else
txt.BackColor = txt.Tag
End If
End Sub
Private Sub CreateAccount_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
For Each ctrl As TextBox In Me.Controls.OfType(Of TextBox)()
AddHandler ctrl.GotFocus, AddressOf FocusChanged
AddHandler ctrl.LostFocus, AddressOf FocusChanged
ctrl.Tag = ctrl.BackColor
Next
End Sub
If you want to add this behavior to all TextBox controls, you're better off deriving your own class from the TextBox class, and override the OnGotFocus and OnLostFocus methods to set the properties accordingly.
Here's how:
Public Class MyTextBox
Inherits TextBox
Protected Overrides Sub OnGotFocus(e As System.EventArgs)
MyBase.OnGotFocus(e)
Me.Tag = Me.BackColor
Me.BackColor = Color.Aqua
End Sub
Protected Overrides Sub OnLostFocus(e As System.EventArgs)
MyBase.OnLostFocus(e)
Me.BackColor = Me.Tag
End Sub
End Class
EDIT: forgot to mention that after adding that class to your project, rebuild the solution, and if it compiles without errors, then your new TextBox class show show up in the VS ToolBox. You can then simply drag & drop onto your form just as any control.
Cheers