Design pattern when moving repeated code out of event handlers - vb.net

I had this code:
Private Sub carButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles carButton.Click
fTrafficSurveyA.incrementCount("Car")
Call updateView()
End Sub
Private Sub bicycleButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bicycleButton.Click
fTrafficSurveyA.incrementCount("Bicycle")
Call updateView()
End Sub
Private Sub lorryButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lorryButton.Click
fTrafficSurveyA.incrementCount("Lorry")
Call updateView()
End Sub
I've changed it to the following:
Private Sub carButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles carButton.Click
ButtonClickCode(CType(sender, Button))
End Sub
Private Sub bicycleButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bicycleButton.Click
ButtonClickCode(CType(sender, Button))
End Sub
Private Sub lorryButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lorryButton.Click
ButtonClickCode(CType(sender, Button))
End Sub
Private Sub ButtonClickCode(ByVal mySender As Button)
Dim incrementVehicle As String
Select Case mySender.Name
Case "carButton"
incrementVehicle = "Car"
Case "bicycleButton"
incrementVehicle = "Bicycle"
Case "lorryButton"
incrementVehicle = "Lorry"
Case Else
incrementVehicle = ""
End Select
fTrafficSurveyA.incrementCount(incrementVehicle)
Call updateView()
End Sub
The new code has more lines of code.
Is the new version better practice, or is there a third pattern that I should be following?
EDIT
Using Guffa's answer + other comments I changed the underlying TrafficSurveyA model to include an enumerated Type and altered it's function incrementCount like so....is this enumerated type is in the correct place?
Enum vehicleType
Car
Lorry
Bicycle
End Enum
Public Sub incrementCount(ByVal vehicle As vehicleType)
' Preconditions: none
' Postconditions: If vehicle is "Car", "Bicycle" or "Lorry" then 1 is added
' to the corresponding count. Otherwise nothing is done.
Select Case vehicle
Case vehicleType.Car : fCars = fCars + 1
Case vehicleType.Bicycle : fBicycles = fBicycles + 1
Case vehicleType.Lorry : fLorries = fLorries + 1
Case Else 'do nothing
End Select
End Sub
The interface code has ended up like this:
Private Sub carButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles carButton.Click
ButtonClickCode(TrafficSurveyA.vehicleType.Car)
End Sub
Private Sub bicycleButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bicycleButton.Click
ButtonClickCode(TrafficSurveyA.vehicleType.Bicycle)
End Sub
Private Sub lorryButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lorryButton.Click
ButtonClickCode(TrafficSurveyA.vehicleType.Lorry)
End Sub
Private Sub ButtonClickCode(ByVal incrementVehicle As TrafficSurveyA.vehicleType)
fTrafficSurveyA.incrementCount(incrementVehicle)
Call updateView()
End Sub

As the code in the event handlers are identcal, you can have just one event handler for all the events:
Private Sub vehicleButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles carButton.Click, bicycleButton.Click, lorryButton.Click
Dim mySender As Button = CType(sender, Button)
Dim incrementVehicle As String
Select Case mySender.Name
Case "carButton"
incrementVehicle = "Car"
Case "bicycleButton"
incrementVehicle = "Bicycle"
Case "lorryButton"
incrementVehicle = "Lorry"
Case Else
incrementVehicle = ""
End Select
fTrafficSurveyA.incrementCount(incrementVehicle)
Call updateView()
End Sub
Another alternative is to keep the separate event handlers, and use the fact that each event handler can send the correct text to the common method, so you don't need to check the control name to determine the text:
Private Sub carButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles carButton.Click
ButtonClickCode("Car")
End Sub
Private Sub bicycleButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bicycleButton.Click
ButtonClickCode("Bicycle")
End Sub
Private Sub lorryButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lorryButton.Click
ButtonClickCode("Lorry")
End Sub
Private Sub ButtonClickCode(ByVal incrementVehicle As String)
fTrafficSurveyA.incrementCount(incrementVehicle)
Call updateView()
End Sub

Related

How do I get the parent form from a child form in VB.net?

I have a VB form which may be called by a number of forms. Upon exiting this child form, I want to restore the calling form but I cannot seem to figure out how to determine which form called it. Any help would be greatly appreciated.
You can create a tagging for parent forms (maybe a global array) which you will update the value every time you open a child form. You just have to remember which form is which on the tagging you will make.
Maybe you can try this-
Module with form tagging:
Module Module1
Public parentForms(2) As String
'parentForms(0) - parent form of Form 1
'parentForms(1) - parent form of Form 2
'parentForms(2) - parent form of Form 3
Public Sub openParentForm(ByVal ParentTag As String)
If ParentTag {use the notequal operator} "" Then
Select Case ParentTag
Case Form1.Tag
Form1.Show()
Case Form2.Tag
Form2.Show()
Case Form3.Tag
Form3.Show()
End Select
End If
End Sub
End Module
Form1:
Public Class Form1
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Me.Tag = "Form1"
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
parentForms(1) = Me.Tag
Form2.Show()
'Dont use .Close as the Parent Form will be disposed and the whole application will exit
Me.Visible = False
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
parentForms(2) = Me.Tag
Form3.Show()
Me.Visible = False
End Sub
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
Call openParentForm(parentForms(0))
End Sub
End Class
Form2
Public Class Form2
Private Sub Form2_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Me.Tag = "Form2"
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
parentForms(0) = Me.Tag
Form1.Show()
Me.Visible = False
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
parentForms(2) = Me.Tag
Form3.Show()
Me.Visible = False
End Sub
Private Sub Form2_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
Call openParentForm(parentForms(1))
End Sub
End Class
Form3
Public Class Form3
Private Sub Form3_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Me.Tag = "Form3"
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
parentForms(0) = Me.Tag
Form1.Show()
Me.Visible = False
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
parentForms(1) = Me.Tag
Form2.Show()
Me.Visible = False
End Sub
Private Sub Form3_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
Call openParentForm(parentForms(2))
End Sub
End Class

Cannot pass variable in Private sub BackgroundWorker [duplicate]

Imports SpeechLib
Public Class Form1
Public vox = CreateObject("sapi.spvoice")
Private Sub cmdSpeak_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdSpeak.Click
Dim text2 As String = "Hello , This is a Text. Hello , This is a Text."
BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub cmdPause_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdPause.Click
vox.pause()
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim SVEPhoneme As Integer = 64
vox.EventInterests = SVEPhoneme
vox.AlertBoundary = SVEPhoneme
End Sub
Private Sub cmdResume_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdResume.Click
vox.resume()
End Sub
Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
vox.Speak(Text, SpeechVoiceSpeakFlags.SVSFlagsAsync)
End Sub
End Class
How can I pass text2 to vox.speak?
In cmdSpeak_Click, pass text2 as a parameter to RunWorkerAsync
BackgroundWorker1.RunWorkerAsync(text2)
In BackgroundWorker1_DoWork, retrieve the value of the parameter
vox.Speak(DirectCast(e.Argument, String), SpeechVoiceSpeakFlags.SVSFlagsAsync)

VB.net Form unexpectingly terminating

Hi I have the following form but cant figureout why its upbrubtly terminiating when difrent buttons are clicked?
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
Private Sub button1_MouseEnter(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.MouseEnter
Dim TEST1 As Integer = System.IO.Directory.GetFiles("C:\test\test").Length
If TEST1 = 0 Then
Me.WebBrowser1.Navigate("http://www.hotmail.com")
End If
End Sub
Private Sub button1_MouseLeave(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.MouseLeave
Me.WebBrowser1.Navigate("http://WWW.facebook.com")
End Sub
Private Sub button2_MouseLeave(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.MouseLeave
Me.WebBrowser1.Navigate("http://WWW.facebook.com")
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Me.WebBrowser1.Navigate("file://C:\test\test")
Button1.Enabled = False
Button2.Enabled = True
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Me.WebBrowser1.Navigate("file://C:\test")
Button2.Enabled = False
Button1.Enabled = True
End Sub
Private Sub button2_MouseEnter(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.MouseEnter
Dim TEST2 As Integer = System.IO.Directory.GetFiles("C:\test\test").Length
If TEST2 = 0 Then
Me.WebBrowser1.Navigate("http://www.hotmail.com")
End If
End Sub
The terms face book and hotmail are just random to keep company site private :)
I suspect the Mouse_Enter event and the Mouse_Leave events are not giving time to the webbrowser to fully load the document and maybe it is internally crashing.
Try checking if the webbrowser has finished working before navigating again and tell us:
Use
If WebBrowser1.ReadyState = WebBrowserReadyState.Complete
Me.WebBrowser1.Navigate("http://www.google.com")
End if

access more components using a thread

I am trying to access a few component using a thread. My form looks like this:
my source looks like this:
Private Sub btnGO_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGO.Click
pbAction.Value = 0
bgwProcess.RunWorkerAsync()
Me.Cursor = Cursors.WaitCursor
End Sub
Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Application.Exit()
End Sub
Private Sub bgwProcess_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgwProcess.DoWork
'a job consists in retrieving data, populating a listview and update the progressbar
'start job 1.1
'do job 1.1 -> ProgressBar1.value+=1
'do job 1.2 -> ProgressBar1.value+=1
'do job 1.3 -> ProgressBar1.value+=1
'start job 2.1 ProgressBar1.value=1
'do job 2.1 -> ProgressBar2.value+=1
'do job 2.2 -> ProgressBar1.value+=1
End Sub
Private Sub bgwProcess_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgwProcess.RunWorkerCompleted
Me.Cursor = Cursors.Default
End Sub
Can anyone help me out?
I have created a class that in the _doWork is populated, and i send it to the _ProgressChanged procedure, where I cand do whatever I want to the component on the form:
Public Class myObj
Public action As String
Public msg As String
Public pbAction As Integer
Public pbMsg As Integer
End Class
...
Private Sub btnGO_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGO.Click
bgwProcess.RunWorkerAsync()
Me.Cursor = Cursors.WaitCursor
End Sub
Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Application.Exit()
End Sub
Private Sub bgwProcess_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgwProcess.DoWork
Dim op As New myObj
op.action = "my action"
op.msg = "My result: Done"
op.pbAction = 1
op.pbMsg = 1
bgwProcess.ReportProgress(0, op)
End Sub
Private Sub bgwProcess_ProgressChanged(ByVal sender As System.Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bgwProcess.ProgressChanged
Dim obj As New myObj
obj = DirectCast(e.UserState, myObj)
myListView.BeginUpdate()
Dim li As New ListViewItem(obj.action, 0)
li.SubItems.Add(obj.msg)
myListView.Items.AddRange(New ListViewItem() {li})
myListView.EndUpdate()
myListView.EnsureVisible(myListView.Items.Count - 1)
myListView.Refresh()
pbAction.Value = obj.pbAction
pbTotal.Value = obj.pbMsg
End Sub
Private Sub bgwProcess_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgwProcess.RunWorkerCompleted
Me.Cursor = Cursors.Default
End Sub

How to pass arguments to a BackGroundWorker

Imports SpeechLib
Public Class Form1
Public vox = CreateObject("sapi.spvoice")
Private Sub cmdSpeak_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdSpeak.Click
Dim text2 As String = "Hello , This is a Text. Hello , This is a Text."
BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub cmdPause_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdPause.Click
vox.pause()
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim SVEPhoneme As Integer = 64
vox.EventInterests = SVEPhoneme
vox.AlertBoundary = SVEPhoneme
End Sub
Private Sub cmdResume_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdResume.Click
vox.resume()
End Sub
Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
vox.Speak(Text, SpeechVoiceSpeakFlags.SVSFlagsAsync)
End Sub
End Class
How can I pass text2 to vox.speak?
In cmdSpeak_Click, pass text2 as a parameter to RunWorkerAsync
BackgroundWorker1.RunWorkerAsync(text2)
In BackgroundWorker1_DoWork, retrieve the value of the parameter
vox.Speak(DirectCast(e.Argument, String), SpeechVoiceSpeakFlags.SVSFlagsAsync)