How to prevent value-changed events from firing on form load in VB.NET
Imagine you want a MsgBox to start if someone trigger an event. When your start the code, the Msgbox is called before the form is completely loaded and likely you get an empty. Look at the code below.
Public Class Form1 Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load With ListBox1 .Enabled = True 'if the listox is enable or disabled .Sorted = True ' if you want ti list sorted .BorderStyle = BorderStyle.Fixed3D ' the border style .Visible = True .ScrollAlwaysVisible = True 'presence of scroll all time .MultiColumn = False 'add a new column if number of items reach max height End With ListBox1.Items.Add("allo1") ListBox1.Items.Add("allo2") ListBox1.Items.Add("allo3") ListBox1.Items.Add("allo4") ListBox1.Items.Add("allo5") ListBox1.Items.Add("allo1") ListBox1.Items.Add("allo2") ListBox1.Items.Add("allo3") ListBox1.Items.Add("allo4") ListBox1.Items.Add("allo5") ListBox1.Items.Add("allo1") ListBox1.Items.Add("allo2") ListBox1.Items.Add("allo3") ListBox1.Items.Add("allo4") ListBox1.Items.Add("allo5") ListBox1.SelectedIndex = 2 '0 is the first one, 2 is the third. ListBox1.SelectedItem = "allo3" 'will always select the first he encounter ListBox1.SelectionMode = SelectionMode.MultiSimple 'no need to use shift or ctrl, only space or left-click ListBox1.SelectionMode = SelectionMode.MultiExtended 'no need to use shift or ctrl with left-click End Sub Private Sub ListBox1_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles ListBox1.SelectedIndexChanged MsgBox(ListBox1.SelectedIndex) End Sub End Class |
Last post wasn�t easy to understand because I wanted to show how a ListBox works. But when the ListBox reacts incorrectly, I feel that I a have to give more details. So now, is time or never to clear things. Is very important to understand how the form is loaded. I will do my best to make it simple.
Step 1 : create the form
We have to do at least something.
Double click your form and you will get this:
Public Class Form1 Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load End Sub End Class |
What you is a class and every in every class, there is a constructor. The constructor is called first, because it create the object. It creates the space in the computer. Creating the object doesn�t means the object is initialized or ready. Again, the constructor new in the class form is :
Hey! Dear computer. I need like 10 Ko of Ram to store this form right now!
Where is the new function?
Let�s be lazy and use Visual Basic Express 2012 or Visual Studio 2012 to print it for us automatically.
Place your cursor anywhere in your form class but outside a function. Go on top of your screen and click on the ComboBox with Declarations in it.
If you choose New, it will put the function at the end of your class. Whatever the function new is printed before the load form function really doesn�t matter. The new function will always be the first function.
So here is the code in the form1 class. You have form1_Load and the New function.
Public Class Form1 Private Sub form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load End Sub Public Sub New() ' This call is required by the designer. InitializeComponent() ' Add any initialization after the InitializeComponent() call. End Sub End Class |
Where is the InitializeComponent ?
Visual Studio or Visual Basic build a function named InitializeComponent. Inside that function, you could find all the little settings you made from the form1.vb Designer.
Each time you place a control in the form, each time you customise the properties of your control inside that form designer, it translate them in the InitializeComponent function.
So where is the InitializeComponent ? Well... instead of telling where to find it, I�ll tell you how to find it.
Place your cursor overt the InitializeComponent, left click on it. Then press F12 on your keyboard. Visual Basic Express or Visual Studio will automatically bring you to the function definition.
And what could we find in that InitializeComponent function? Well see it for yourself. Simple settings.
So what do we have to understand? The program creates the form1 object using the new function. Then it calls the InitializeComponent inside that New function. The InitializeComponent set some general properties like size , color, and so on.
Ok, is time to move to the next step.
Step 3 : insert an event.
Alright, in the form I simply inserted and ListBox. To be honest, you could insert any control. It is really not important. Our goal here is to understand how thing works. The more you understand, the more you get better.
From the form designer, insert a ListBox. Double-click on that ListBox. Normally, your code should look like this:
Public Class Form1 Private Sub form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load End Sub Public Sub New() ' This call is required by the designer. InitializeComponent() ' Add any initialization after the InitializeComponent() call. End Sub Private Sub ListBox1_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles ListBox1.SelectedIndexChanged End Sub End Class |
Your cursor should be in the ListBox1_SelectedIndexChanged function. That function whatever is called is really not important. You could rename it. What is important is at the end of the function line, there is a little phrase like this:
Handles ListBox1.SelectedIndexChanged |
Please don�t try to change that part.
Now, I want you to bring another event function from the ListBox1. Left-click inside the SelectedIndexChanged function and then try to click the ComboBox in the top right of your Visual Basic Express or Visual Studio. Look for the SizeChanged event and select it.
You should have a new ListBox1_SelectedIndexChanged function. OK. Now place a Msgbox and write something in it.
Private Sub ListBox1_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles ListBox1.SelectedIndexChanged MsgBox("I love pizza") End Sub |
Now run the program and notice what is happening.
You might get the Msgbox box 4 times. It happens to me 4 times�. And then the form loads.
Again what is happening? Each time the ListBox is resized, it calls the event function. But it calls it 4 times? What is going on?
Well, the first one is relatively easy to find out. The first time the function ListBox1_SizeChanged is called is in the InitializeComponent function. When the program set the size of your ListBox1.
Me.ListBox1.Size = New System.Drawing.Size(195, 199) |
You could try to surround the code with a lot of MsgBox to really get it. Here the code with the MsgBox:
This is form1.vb
Public Class Form1 Private Sub form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load End Sub Public Sub New() MsgBox("Function New : Started") ' This call is required by the designer. InitializeComponent() MsgBox("Function New : back to New Function") ' Add any initialization after the InitializeComponent() call. End Sub Private Sub ListBox1_Resize(sender As Object, e As System.EventArgs) Handles ListBox1.Resize ''Msgbox("ListBox1_Resize") 'Dim oListBox As ListBox 'oListBox = sender 'MsgBox(oListBox.Size.Width & " " & oListBox.Size.Height) End Sub Private Sub ListBox1_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles ListBox1.SelectedIndexChanged 'Msgbox("I love pizza") End Sub Private Sub ListBox1_SizeChanged(sender As Object, e As System.EventArgs) Handles ListBox1.SizeChanged MsgBox("I love Hot Dog") End Sub End Class |
And form1.vb [Designer]
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _ Partial Class Form1 Inherits System.Windows.Forms.Form 'Form overrides dispose to clean up the component list. <System.Diagnostics.DebuggerNonUserCode()> _ 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. <System.Diagnostics.DebuggerStepThrough()> _ Private Sub InitializeComponent() MsgBox("Function InitializeComponent : Starting") Me.ListBox1 = New System.Windows.Forms.ListBox() MsgBox("Function InitializeComponent : ListBox1 Created") Me.SuspendLayout() ' 'ListBox1 ' Me.ListBox1.FormattingEnabled = True Me.ListBox1.Location = New System.Drawing.Point(30, 38) Me.ListBox1.Name = "ListBox1" Me.ListBox1.ScrollAlwaysVisible = True MsgBox("Function InitializeComponent : ListBox1 will get size") Me.ListBox1.Size = New System.Drawing.Size(195, 199) MsgBox("Function InitializeComponent : ListBox1 got the size") Me.ListBox1.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(284, 255) Me.Controls.Add(Me.ListBox1) Me.Name = "Form1" Me.Text = "Form1" Me.ResumeLayout(False) MsgBox("Function InitializeComponent : Leaving Function") End Sub Friend WithEvents ListBox1 As System.Windows.Forms.ListBox End Class |
The ListBox1 event is called one first time after we put a dimension in the ListBox1. For the 3 others times the event is called, they are no way we could easily know where they are coming from. Besides, there is no point to know exactly how they are called or why. People designed the System.Windows.Forms.ListBox to inherit other Controls. Those Controls Inherits others Objects and so on.
The simplest way to fix our problem, is the put a kind of switch that prevent our event from firing from the beginning and to put that switch to On when the form is completely loaded.
Using the form1�s build-in function called OnShown will help us.
Step 4: Overriding the OnShown function:
Your class form1 is built from a parent class called System.Windows.Forms.Form
Some functions in System.Windows.Forms.Form are very accessible like the events or the new function while other are harder to get.
To use those function, you need to use the Overrides to override a hidden function inside System.Windows.Forms.Form
Honestly, is not very important to fully understand how things are called or how thing works. Today, is time to use that function at our own advantage.
So let�s override the OnShown function and use it:
Protected Overrides Sub OnShown(e As System.EventArgs) MyBase.OnShown(e) End Sub |
Step 5: Placing the on-off variable:
You almost completed your mission. Is time to add a variable in your class. That variable will stop your code from firing events.
Your function is now available, we could put on and off Boolean to activate or disable the ListBox event.
I decided to name it EventsOn and I set it to false right at the beginning of the New function. I set the Boolean EventsOn at true once all my initial variables are set.
Here is what your code would look like with the Msgbox adjusted and with initial items in the List Box
Public Class Form1 Private EventsOn As Boolean Protected Overrides Sub OnShown(e As System.EventArgs) MyBase.OnShown(e) EventsOn = True End Sub Private Sub form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load End Sub Public Sub New() 'MsgBox("Function New : Started") EventsOn = False ' This call is required by the designer. InitializeComponent() 'MsgBox("Function New : back to New Function") ' Add any initialization after the InitializeComponent() call. ListBox1.Items.Add("click me") ListBox1.Items.Add("click here") End Sub Private Sub ListBox1_Resize(sender As Object, e As System.EventArgs) Handles ListBox1.Resize ''Msgbox("ListBox1_Resize") 'Dim oListBox As ListBox 'oListBox = sender 'MsgBox(oListBox.Size.Width & " " & oListBox.Size.Height) End Sub Private Sub ListBox1_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles ListBox1.SelectedIndexChanged If EventsOn = True Then MsgBox("I love pizza") End If End Sub Private Sub ListBox1_SizeChanged(sender As Object, e As System.EventArgs) Handles ListBox1.SizeChanged If EventsOn = True Then MsgBox("I love Hot Dog") End If End Sub End Class |
Final result:
Download: ListBoxSample.zip
Update Contact :
No Wa/Telepon (puat) : 085267792168
No Wa/Telepon (fajar) : 085369237896
Email : Fajarudinsidik@gmail.com
No Wa/Telepon (puat) : 085267792168
No Wa/Telepon (fajar) : 085369237896
Email: Fajarudinsidik@gmail.com
atau Kirimkan Private messanger melalui email dengan klik tombol order dibawah ini :