Backgroundworker gives multiple error messages - vb.net

I have a form with three textboxes in it. In my BackgroundWorker1_DoWork handler I test if any TextBox is empty and launch a MessageBox asking the user to fill in all the TextBoxes. This is done in a Try/Catch block. My problem is two fold. If the TextBoxes aren't filled in the user gets the first MessageBox and then another MessageBox when the Catch exception is thrown...so this would be the second MessageBox the user gets. In my BackGroundWorker1_RunWorkCompleted handler I test if an Exception is thrown. It never acknowledges the error and immediately executes the Else block which will be the third message box the user receives saying "Process complete." The Process Complete should not have been shown.
How do I test if there are any TextBoxes not filled in and if they're not throw 1 MessageBox telling the user to fill in all the TextBoxes? And make my RunWorkerComplete handler acknowledge the ElseIf e.Error IsNot Nothing.
Thank you for your help.
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
BackgroundWorker1.WorkerReportsProgress = True
Try
For Each cntrl As Control In Me.Controls()
If TypeOf cntrl Is TextBox Then
If CType(cntrl, TextBox).Text.Equals(String.Empty) Or (CType(cntrl, TextBox).Text = "") Then
cntrl.BackColor = Color.Yellow
MessageBox.Show("Please enter value in all fields on form" & cntrl.Name.ToString())
cntrl.Focus()
End If
End If
Next
runProgram()
Catch ex As Exception
MessageBox.Show("An error occured while trying to load this application. Please contact Maxine Hammett for assistance " &
vbNewLine & "" & vbNewLine & String.Format("Error: {0}", ex.Message))
End Try
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
If e.Cancelled = True Then
MsgBox(" Operation Cancelled ")
ProgressBar1.Value = 0
ElseIf e.Error IsNot Nothing Then
MsgBox("Error in RunWorkerComplete" & e.Error.Message)
Else
MsgBox(" Process Complete ")
Close()
End If
End Sub
Moved the control checking to the execute button. But now I get errors about the text boxes not having a path (one of the text boxes is a path to folder).
Private Sub btnExecute_Click(sender As Object, e As EventArgs) Handles btnExecute.Click
Dim launchProgram As Boolean = False
While launchProgram = False
For Each cntrl As Control In Me.Controls()
If TypeOf cntrl Is TextBox Then
If CType(cntrl, TextBox).Text.Equals(String.Empty) Or (CType(cntrl, TextBox).Text = "") Then
cntrl.BackColor = Color.Yellow
MessageBox.Show("Please enter value in all fields on form" & cntrl.Name.ToString())
cntrl.Focus()
launchProgram = False
Else
launchProgram = True
End If
End If
Next
End While
If launchProgram = True Then
BackgroundWorker1.RunWorkerAsync()
End If
End Sub

I suggest that you check a single text box a time and show the message if its empty:
Private Sub btnExecute_Click(sender As Object, e As EventArgs) Handles btnExecute.Click
For Each cntrl As TextBox In Controls.OfType(Of TextBox)
If String.IsNullOrEmpty(cntrl.Text) Then
cntrl.BackColor = Color.Yellow
MessageBox.Show("Please enter value in all fields on form" & cntrl.Name.ToString())
cntrl.Focus()
Return
Else
cntrl.BackColor = SystemColors.Window
End If
Next
BackgroundWorker1.RunWorkerAsync()
End Sub
Or maybe concatenate the names of the empty text boxes in the For..Each block if you really need to prompt the user this way:
Private Sub btnExecute_Click(sender As Object, e As EventArgs) Handles btnExecute.Click
Dim sb As New StringBuilder
For Each cntrl As TextBox In Controls.OfType(Of TextBox)
If String.IsNullOrEmpty(cntrl.Text) Then
If sb.Length > 0 Then sb.Append(", ")
sb.Append(cntrl.Name)
cntrl.BackColor = Color.Yellow
Else
cntrl.BackColor = SystemColors.Window
End If
Next
If sb.Length > 0 Then
MessageBox.Show("Please enter value in all fields on form" & sb.ToString())
Controls.OfType(Of TextBox).Where(Function(a) String.IsNullOrEmpty(a.Text)).FirstOrDefault?.Focus()
Return
End If
BackgroundWorker1.RunWorkerAsync()
End Sub
Otherwise, run the worker.
Good luck.

Related

Pass Information between 2 Forms - VB.Net - Winforms

I have 2 Forms in a Product Registration Project
The 1st form has 3 buttons: New | Consult | Change | - that call the 2nd Form where I have a Photo Button.
New Button:
Private Sub tsbNew_Click(sender As Object, e As EventArgs) Handles tsbNew.Click
Try
Using frm As New frm2ndForm
frm.txtPrdCod.Enabled = True
frm.txtPrdCod.Text = ""
frm.ShowDialog()
End Using
tsbRefresh.PerformClick()
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical)
End Try
End Sub
Consult Button:
Private Sub tsbConsult_Click(sender As Object, e As EventArgs) Handles tsbConsult.Click
Try
If DGProds.CurrentRow Is Nothing Then
MessageBox.Show("Select one product")
Exit Sub
End If
Using frm As New frm2ndForm
frm.txtPrdCod.Enabled = False
frm.txtPrdCod.Text = DGProds.CurrentRow.Cells("prdCod").Value.ToString.Trim 'dr.Item("prdCod")
frm.txtDes.Enabled = False
frm.txtDesRed.Enabled = False
frm.ShowDialog()
End Using
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical)
Exit Sub
End Try
End Sub
Change Button
Private Sub tsbChange_Click(sender As Object, e As EventArgs) Handles tsbChange.Click
Try
If DGProds.CurrentRow Is Nothing Then
MessageBox.Show("Select one product")
Exit Sub
End If
Using frm As New frm2ndForm
frm.txtPrdCod.Enabled = False
frm.txtPrdCod.Text = DGProds.CurrentRow.Cells("prdCod").Value.ToString.Trim 'dr.Item("prdCod")
frm.ShowDialog()
End Using
tsbRefresh.PerformClick()
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical)
End Try
End Sub
In the 2nd Form, the Photo button will have two different behaviors:
when the user has clicked on the "New" button on Form 1, the code will open a search screen for the user to select an image in a folder on the Photos in server and show it in the picturebox1 in Form 2;
when the user has clicked on the "Consult" or "Change" button on Form 1, the code will make a comparison between the prdCod field of the Products Table and the filename of the image in the Photos folder and, when found, will show the image in the picturebox1 in Form 2.
If the "clicked button" on form 1 is "New", do the commands below:
Private Sub btnPhoto_Click(sender As Object, e As EventArgs) Handles btnPhoto.Click
Using open As New OpenFileDialog With {
.Title = "Select Photo",
.FileName = "",
.Filter = "Images PNG,JPEG,BMP,JPG|*.png;*.jpeg";*.bmp;*.jpg,
.Multiselect = False}
If open.ShowDialog = DialogResult.OK Then
PictureBox1.Image = Image.FromFile(open.FileName)
End If
End Using
End Sub
If the "clicked button" on form 1 is "Consult or Change", execute the commands below:
Private Sub btnPhoto_Click(sender As Object, e As EventArgs) Handles btnPhoto.Click
Dim IdProduto As String = prdCod ***field Products Table that will be used for the search in the Photos folder
If File.Exists("\\server\cmg\projects\Photos" & IdProduto) Then ***Search the image from the Photos folder on the server
PictureBox1.Image = Image.FromFile("\\server\cmg\projects\Photos" & IdProduto)
End If
End Sub
How do I check which button was clicked on the 1st form to be able to perform the correct Private Sub on the 2nd form?
It worked:
In the first form (frmConsProd), in the New Button code (tsbNew_Click), I include the parameter that will be sent to
the second form (frmCadProd):
Public Class frmConsProd
Private Sub tsbNew_Click(sender As Object, e As EventArgs) Handles tsbNew.Click
Try
Using frm As New frmCadProd("New")
frm.txtPrdCod.Enabled = True
frm.txtPrdCod.Text = ""
frm.ShowDialog()
End Using
tsbRefresh.PerformClick()
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical)
End Try
End Sub
End Class
In the second form (frmCadProd) I created a class variable (_operation) and the constructor (Public Sub New) to receive the sent parameter:
Public Class frmCadProd
Dim _operation As String
Public Sub New(operation As String)
InitializeComponente()
Select Case operation.ToLower()
Case "new"
_operation = operation
Case Else
MessageBox.Show("Invalid option!")
Close()
End Select
End Sub
End Class
Thanks to Messrs. #F0r3v3r-A-N00b, #jmcilhinney e #user09938, for the help.

Catching a [Tab] or [Enter] on KeyPress Event

Is it possible to catch the Enter or Tab key in the KeyPress Event?
I am entering a numeric only value on a comboBox, but once this value has been validated I want the user to be able to either Tab or Enter out of the CB once validated, is this possible from within the keyPress? Here's my code;
Private Sub cbCheckAmount_KeyPress(sender As Object, e As KeyPressEventArgs) Handles cbCheckAmount.KeyPress
'Only allowed characters
Dim allowedChars As String = "0123456789."
If Char.IsDigit(e.KeyChar) = False And Char.IsControl(e.KeyChar) = False Then
If e.KeyChar <> ControlChars.Back Then
If allowedChars.IndexOf(e.KeyChar) = -1 Then
' Invalid Character, notify clear and return
nonNumberEntered = True 'Set to True to 'swallow' the keypress and prevent the TextChanged event from firing.
MsgBox("Numbers only", MsgBoxStyle.Exclamation)
cbCheckAmount.Text = ""
cbCheckAmount.Focus()
cbDollarAmount.Text = ""
End If
End If
End If
'If shift key was pressed, it's not a number.
If Control.ModifierKeys = Keys.Shift Then
nonNumberEntered = True
cbCheckAmount.Text = ""
cbCheckAmount.Focus()
End If
End Sub
Private Sub cbCheckAmount_TextChanged(sender As Object, e As EventArgs) Handles cbCheckAmount.TextChanged
'Call the function to create a text line out of the numbers
'Regex to ensure the string contains numbers
Dim t As ComboBox = sender
Dim foo As Decimal
If Decimal.TryParse(cbCheckAmount.Text, foo) Then
'data is good
Dim re As New Text.RegularExpressions.Regex("\d")
If re.IsMatch(cbCheckAmount.Text) Then
If nonNumberEntered = False Then
Dim newNum = cbCheckAmount.Text.Trim
'If there are any leading weird . in the string
newNum = newNum.TrimStart(".")
Dim newStr As String
'Build the array
Dim newDec As String() = newNum.Split(New Char() {"."c})
If newNum.Contains(".") Then
newStr = NumberToText(newDec(0))
cbDollarAmount.Text = newStr & " Dollars and " & newDec(1) & "/100 "
Else
newStr = NumberToText(newDec(0))
cbDollarAmount.Text = newStr & " Dollars and 00/100 "
End If
End If
End If
Else
'data is bad
nonNumberEntered = False
cbCheckAmount.Text = ""
cbCheckAmount.Focus()
cbDollarAmount.Text = ""
End If
End Sub
I'm using VB 2015
Stop and listen. The problem you're trying to solve doesn't exist. Just do it properly in the first place. Handle the Validating event of each control and do your validation there. If validation fails, set e.Cancel to True and the control will retain focus. In the Click event handler of your OK Button or whatever, call the ValidateChildren method and that will raise the Validating event on every control, even if it never received focus. If any controls fail validation, ValidateChildren returns False and you know not to try to use the data. E.g.
Private Sub TextBox1_Validating(sender As Object, e As CancelEventArgs) Handles TextBox1.Validating
Dim value = TextBox1.Text.Trim()
'Data is optional but must be numeric if provided.
If value <> String.Empty AndAlso Not Double.TryParse(value, Nothing) Then
TextBox1.SelectAll()
TextBox1.HideSelection = False
MessageBox.Show("If data is provided, it must be numeric", "Invalid Data", MessageBoxButtons.OK, MessageBoxIcon.Error)
TextBox1.HideSelection = True
e.Cancel = True
End If
End Sub
Private Sub TextBox2_Validating(sender As Object, e As CancelEventArgs) Handles TextBox2.Validating
'Data is required.
If TextBox2.Text.Trim() = String.Empty Then
TextBox2.SelectAll()
TextBox2.HideSelection = False
MessageBox.Show("Data must be provided", "Invalid Data", MessageBoxButtons.OK, MessageBoxIcon.Error)
TextBox2.HideSelection = True
e.Cancel = True
End If
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If ValidateChildren() Then
'The data has passed validation so it is safe to use it.
End If
End Sub
If i understand correctly isnt what you want just
If e.KeyChar = ChrW(Keys.Return) or e.KeyChar = Keys.Tab Then
''somethign something''
End If

Listview disable certain check box once checked

Please help me with this!
I have a ListView with checkboxes enabled. I need to disable all the checked items checkboxes, where the user should not try to click it again.
Here is my code, where I am getting error.
Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
Try
' submit
Dim path As String = "C:\Users\jtb43661\Documents\Visual Studio 2017\Projects\IGI Event Tracker\IGI Event Tracker\bin\Debug\Logs\Event.LOG"
If Not File.Exists(path) Then
Using sw As StreamWriter = File.CreateText(path)
End Using
End If
Using sw As StreamWriter = File.AppendText(path)
For Each item In ListView1.CheckedItems
sw.WriteLine(item.Text & "->" & " Completed-#---> " & Label2.Text)
item.SubItems.Add("Completed")
item.BackColor = Color.GreenYellow
'If item.subItems.text = "Completed" Then
'here I need to disable or lock the checked checkboxes
'End If
Next
sw.Close()
End Using
MsgBox("Events Submitted Successfully")
Catch ex As Exception
MsgBox(ex.Message.ToString)
Finally
End Try
End Sub
If I understand your implied logic correctly, once a ListviewItem is checked and contains a ListViewSubItem with the Text property equal to "Completed" you do not want the user to be able to uncheck that item. The addition of the "Completed" subitem is performed in a Button click event handler something like this:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
For Each itm As ListViewItem In ListView1.CheckedItems
' add "Completed" subitem only if it does not currently exist
Dim hasCompleted As Boolean = False
For Each subitem As ListViewItem.ListViewSubItem In itm.SubItems
hasCompleted = subitem.Text.Equals("Completed")
If hasCompleted Then Exit For
Next
If Not hasCompleted Then itm.SubItems.Add("Completed")
Next
End Sub
As far as I know, there is no way to directly disable a ListViewItem to prevent it from being unchecked. However, the ListView does have the ItemCheck event that can be used to prevent changing the "Checked" state. The following code prevents the Checked state change if the item being "UnChecked" has a SubItem with the Text "Completed".
Private Sub ListView1_ItemCheck(sender As Object, e As ItemCheckEventArgs) Handles ListView1.ItemCheck
If e.CurrentValue = CheckState.Checked Then
Dim item As ListViewItem = ListView1.Items(e.Index)
For Each subitem As ListViewItem.ListViewSubItem In item.SubItems
If subitem.Text.Equals("Completed") Then
e.NewValue = e.CurrentValue ' do not allow the change
Exit For
End If
Next
End If
End Sub

Multiple buttons, one event to change clicked button colour

The code shown below should allow any button on the page to change colour except for the ones named in the first if statement. This code was working but now does nothing when the button is clicked. The button should turn yellow but just stays the default colour. Also is there anyway I can manipulate the code so only one button can be red at a time instead of allowing multiple red buttons. When reading into this. I cannot find any help for vb. Can anyone help?
Personally, I think it may be to do with thePublic Sub since the message box does not appear when a field is empty.
Public Sub btn_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Click
Try
Dim btn As Button = sender
If btn.Name = "BtnUpdate" Or btn.Name = "BtnBackCust" Or btn.Name = "BtnConfirm" Then
ElseIf TxtFirstName.Text = "" Or TxtLastName.Text = "" Or TxtAddress.Text = "" Or cboCountry.SelectedItem = "" Or cboRoomType.SelectedItem = "" Then
MsgBox("You must populate all fields")
Else
btn.BackColor = Color.Red
btn.Text = ChosenRoom
End If
Catch ex As Exception
End Try
End Sub
Instead of using the MyBase.Click Event, create an Handle for each Button on your Form Load:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For Each Button As Button In Me.Controls.OfType(Of Button)()
If Button.Name <> "BtnUpdate" AndAlso Button.Name <> "BtnBackCust" AndAlso Button.Name <> "BtnConfirm" Then
AddHandler Button.Click, AddressOf ChangeColor
End If
Next
End Sub
The ChangeColor sub, also create the RedButton variable to keep track of what is the currently red button:
Private RedButton As Button = Nothing
Private Sub ChangeColor(Sender As Object, e As EventArgs)
If TypeOf Sender Is Button Then
If TxtFirstName.Text = "" OrElse TxtLastName.Text = "" OrElse TxtAddress.Text = "" OrElse cboCountry.SelectedItem = "" OrElse cboRoomType.SelectedItem = "" Then
MsgBox("You must populate all fields")
Else
Dim SenderButton As Button = Sender
If RedButton IsNot Nothing Then
RedButton.BackColor = Me.BackColor
End If
If SenderButton IsNot RedButton Then 'This if will toogle the button between Red and the Normal color
SenderButton.BackColor = Color.Red
End If
RedButton = Sender
End If
End If
End Sub

VB.Net SelectedChangeCommitted Throwing Error

I am really annoyed here. I don't understand why this event keeps throwing a blank error. Below is my code.
Private Sub cboSections_SelectedChangeCommitted(sender As System.Object, e As System.EventArgs) Handles cboSections.SelectionChangeCommitted
On Error GoTo EH
If TypeOf sender Is Windows.Forms.ComboBox Then
'some boolean that checks if we are skipping this event, thus it does if so
If mbSkipEvent Then Exit Sub
'checks if index that was changed to is > 0 then it toggles the bottom command buttons
If cboSections.SelectedIndex > 0 Then
ToggleCmdButtons(True)
Else
ToggleCmdButtons(False)
End If
'sets the string msPurpose
msPurpose = "Show Section"
Debug.Print("Im here")
End If
EH:
Debug.Print("Error Description: " & Err.Description)
End Sub
In my output I get "Error Description: ". Thats it. If anyone has any solution or point in the right direction that would be great.
Let's try some real error handling and see if you get anything better. While we're at it, we can simplify the code a bit:
Private Sub cboSections_SelectedChangeCommitted(sender As System.Object, e As System.EventArgs) Handles cboSections.SelectionChangeCommitted
Dim comboBox = TryCast(sender, ComboBox)
If comboBox Is Nothing OrElse mbSkipEvent Then Exit Sub
Try
'checks if index that was changed to is > 0 then it toggles the bottom command buttons
ToggleCmdButtons(cboSections.SelectedIndex > 0)
'sets the string msPurpose
msPurpose = "Show Section"
Debug.Print("Im here")
Catch Ex As Exception
Debug.Print("Error Description: " & Ex.Message)
End Try
End Sub