VB - 在触发退格键后,TextChanged无法正确触发?

时间:2016-02-02 22:56:17

标签: vb.net

我的问题归结为:

我有六个TextBox,它们期望一个介于0和给定数字之间的值。 我想要实现的是:

  • 如果输入的数字介于0和指定的数字(作为标签)之间,则文本将保持黑色
  • 如果输入的数字超过指定的数字,则文字将变为红色

这里的问题是,如果指定的数字是" 10",并且用户输入11,它将变为红色,但是,如果他们点击退格键(现在输入的数字) 1)数字保持红色,这不是预期的功能 - 数字1应该是黑色的,因为它在0和指定的数字之间。

所有指定的号码现在都是硬编码的(我在初学者课程中这只是我为了增加程序功能而做的事情而且我没有'我们已经为每个" Assignment"添加了课程,你可以从技术上输入负数,我现在不关心这个。

这是子程序,它被添加为某个GroupBox中所有文本框的处理程序

' Handler which gets added to all TextBoxes in "grpGrades" GroupBox
    Private Sub txtGradePoints_TextChanged(sender As Object, e As EventArgs)

        ' Take in generic sender (Textbox) and convert to TextBox (necessary due to Strict mode)
        Dim textBox = CType(sender, TextBox)
        Try
            ' the value of the current TextBox being checked
            Dim val = Decimal.Parse(textBox.Text)
            Select Case textBox.Name
                Case "txtPostPoints"
                    If val > 10 Then textBox.ForeColor = Color.Red
                Case "txtCh1TestPoints", "txtCh2TestPoints", "txtCh3TestPoints"
                    If val > 50 Then textBox.ForeColor = Color.Red
                Case "txtCh2TutPoints", "txtCh3TutPoints"
                    If val > 25 Then textBox.ForeColor = Color.Red
                Case Else
                    textBox.ForeColor = Color.Black

            End Select
        Catch
            textBox.ForeColor = SystemColors.ControlText
        End Try


    End Sub

这是onLoad Handler,它从" grpGrades"中获取相应的TextBox控件。 GroupBox并将上述TextChanged处理程序添加到每个处理程序。

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        ' Get array of TextBox Controls from the "grpGrades" GroupBox
        Dim textBoxes = grpGrades.Controls.OfType(Of TextBox)()

        ' Go through the array of TextBoxes and add the TextChanged handler to each TextChanged event
        For Each txt In textBoxes
            AddHandler txt.TextChanged, AddressOf txtGradePoints_TextChanged
        Next

        'AddHandler txtPostPoints.TextChanged, AddressOf txtGradePoints_TextChanged
        'AddHandler txtCh1TestPoints.TextChanged, AddressOf txtGradePoints_TextChanged
        'AddHandler txtCh2TestPoints.TextChanged, AddressOf txtGradePoints_TextChanged
        'AddHandler txtCh3TestPoints.TextChanged, AddressOf txtGradePoints_TextChanged
        'AddHandler txtCh2TutPoints.TextChanged, AddressOf txtGradePoints_TextChanged
        'AddHandler txtCh3TutPoints.TextChanged, AddressOf txtGradePoints_TextChanged
    End Sub

子例程的最后一部分只是注释掉的代码,是我最初添加处理程序的方式,以防我的新方法出现问题。

编辑:是否真的有必要进行投票?是什么原因?

3 个答案:

答案 0 :(得分:4)

您的代码从不测试有效值。将当前文本框设置为黑色的Case Else永远不会在当前文本框返回有效值时被点击。这不可能发生,因为Select Case将匹配文本框的当前名称,将再次测试无效值,然后退出Select Case块。您需要在当前文本框名称的相应Case中设置有效值的颜色。 IF conditional operator可以将所有内容减少到一行

Private Sub txtGradePoints_TextChanged(sender As Object, e As EventArgs)

    ' Take in generic sender (Textbox) and convert to TextBox (necessary due to Strict mode)
    Dim textBox = CType(sender, TextBox)
    Try
        ' the value of the current TextBox being checked
        Dim val = Decimal.Parse(textBox.Text)
        Select Case textBox.Name
            Case "txtPostPoints"
                textBox.ForeColor = IF(val > 10, Color.Red, Color.Black)
            Case "txtCh1TestPoints", "txtCh2TestPoints", "txtCh3TestPoints"
                textBox.ForeColor = IF(val > 50, Color.Red, Color.Black)
            Case "txtCh2TutPoints", "txtCh3TutPoints"
                textBox.ForeColor = IF(val > 25, Color.Red, Color.Black)
            Case Else
                ' Not sure if it is needed for other textboxes....
                textBox.ForeColor = Color.Black

        End Select
    Catch
        textBox.ForeColor = SystemColors.ControlText
    End Try


End Sub

答案 1 :(得分:2)

所以,正如其他人所说,你不会为每个文本框处理If的两面。如果颜色符合条件,则设置颜色,但不反转颜色。

这是我处理这个问题的方法。它有点不同,但它将所有代码保存在一起,并且不需要任何Case代码来计算调用文本框的名称。

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    Dim check As Func(Of TextBox, Decimal, Boolean) =
        Function(tb, d)
            Dim value As Decimal
            If (Decimal.TryParse(tb.Text, value)) Then
                Return value > d
            End If
            Return False
        End Function

    Dim add As Action(Of TextBox, Decimal) =
        Sub(tb, d)
            AddHandler tb.TextChanged,
            Sub(s, e2)
                tb.ForeColor = If(check(tb, d), Color.Red, Color.Black)
            End Sub
        End Sub

    add(txtPostPoints, 10)
    add(txtCh1TestPoints, 50)
    add(txtCh2TestPoints, 50)
    add(txtCh3TestPoints, 50)
    add(txtCh2TutPoints, 25)
    add(txtCh3TutPoints, 25)

End Sub

因此,check是一个Func(Of TextBox, Decimal, Boolean),它接受​​TextBox并安全地解析其文本以查看它是否大于Decimal值并返回True如果是,那么False

add是一个Action(Of TextBox, Decimal),需要TextBoxDecimal并添加处理程序以调用check将颜色设置为红色或黑色关于check的结果。

为每个add调用TextBox非常简单。

所有硬编码都没有魔术字符串检查,所有这些都很好地封装在表单加载方法中。

答案 2 :(得分:1)

您正在使用基于名称的选择案例,唯一的条件是,如果它是> 10然后将前景变成红色。但你永远不会把它拒之门外。现在,在你提起案件之前,让我告诉你,其他情况只会基于textbox.name,因为找到了名字,否则其他人不会在这里玩。

因此,当找到名称时,请检查值> 10,并设置为红色,但如果不是,则不要告诉它该做什么。 10