Loop through empty textbox until the textbox has d

2020-05-10 07:44发布

问题:

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

回答1:

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...

  1. Only list the TextBoxes once in some kind of IEnumerable collection.
  2. Use LINQ to help you with some of the logic.
  3. 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


回答2:

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