I'm sure there's a simple solution on this, but it escapes me. I have a form with three text boxes on it. Before the main code is run I want to make sure each text box has data in it. I've initialized "hasData" to be the variable that will decide if the code can move on or not. I evaluate hasData in a Do While loop but the code discovers there are text boxes without data and set hasData variable to "False". But then I'm in a continuous loop, the message box never goes away to allow you to enter text into the empty text boxes.
Thank you for your help.
Dim hasData As String
hasData = "False"
Do While hasData = "False"
If txtTechManName.Text.Trim = "" Or txtDirectory.Text.Trim = "" Or txtBxUnique.Text.Trim = "" Then
btnExecute.Enabled = False
hasData = "False"
MsgBox(" Please fill all text boxes on form ")
' this resulted in an endless loop of the msgBox. It didn't let me add text to the empty fields
Else
btnExecute.Enabled = True
hasData = "True"
End If
Loop
If (hasData = "True") Then
searchDir = txtDirectory.Text
Prefix = txtBxUnique.Text
Dim manualName = txtTechManName.Text
Do you see how you had to list the TextBoxes twice? The list of controls is the same in both cases, so why do double work?
If txtTechManName.Text.Trim = "" Or txtDirectory.Text.Trim = "" Or txtBxUnique.Text.Trim = "" Then
' ...
If txtTechManName.Text.Trim = "" Then
txtTechManName.Focus()
' ...
If you ever wanted to add a TextBox to the logic, then you'd have to remember to update the code in two places. You may even have more than two places...
- Only list the TextBoxes once in some kind of IEnumerable collection.
- Use LINQ to help you with some of the logic.
- Use methods to encapsulate the logic, so your program flow is smoother and easier to understand.
' store the TextBoxes in a collection
Private ReadOnly textBoxes As New List(Of TextBox)()
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' add the TextBoxes which should be filled to the collection
textBoxes.AddRange({txtTechManName, txtDirectory, txtBxUnique})
End Sub
Private Function hasData() As Boolean
' ![any TextBox is invalid] == all TextBoxes are valid
Return Not textBoxes.Any(AddressOf textBoxIsInvalid)
End Function
Private Function lastInvalidTextBox() As TextBox
' last TextBox with invalid entry, or default (null)
Return textBoxes.LastOrDefault(AddressOf textBoxIsInvalid)
End Function
' returns true when passed TextBox is invalid
Private Function textBoxIsInvalid(tb As TextBox) As Boolean
' define invalid here, in once place only
Return String.IsNullOrWhiteSpace(tb.Text)
End Function
Private Sub btnExecute_Click(sender As Object, e As EventArgs) Handles btnExecute.Click
' simply checks the hasData function which hides the logic
If hasData() Then
runProgram()
Else
MessageBox.Show("Please fill all text boxes on form")
' focus the last invalid TextBox, effectively the same as your original logic
' if it is null (no invalid TextBox, see lastInvalidTextBox()), isn't called
lastInvalidTextBox()?.Focus()
End If
End Sub
I moved my evaluating condition to the execute buttons on click event. There I run an if statement and when hasData is true run the function with the rest of the code.
Private Sub btnExecute_Click(sender As Object, e As EventArgs) Handles btnExecute.Click
Dim hasData As Boolean = False
If txtTechManName.Text.Trim = "" Or txtDirectory.Text.Trim = "" Or txtBxUnique.Text.Trim = "" Then
hasData = False
MsgBox(" Please fill all text boxes on form ")
If txtTechManName.Text.Trim = "" Then
txtTechManName.Focus()
ElseIf txtDirectory.Text.Trim = "" Then
txtDirectory.Focus()
ElseIf txtBxUnique.Text.Trim = "" Then
txtBxUnique.Focus()
End If
Else
hasData = True
runProgram()
End If
End Sub