Vb.net VB-文本更改在按下退格键后未正确触发?

Vb.net VB-文本更改在按下退格键后未正确触发?,vb.net,Vb.net,我的问题归结为: 我有六个文本框,它们期望值介于0和给定数字之间。 我努力实现的目标是: 如果输入的数字介于0和指定数字(作为标签)之间,文本将保持黑色 如果输入的数字超过指定的数字,文本将变为红色 这里的问题是,如果指定的数字是“10”,并且用户输入11,它将变为红色,这是应该的,但是,如果他们按退格键(输入的数字现在是1),数字将保持红色,这不是预期的功能-数字1应为黑色,因为它介于0和指定的数字之间 所有指定的数字现在都是硬编码的(我正在学习一门初学者课程,这只是为了增加程序的功能而做

我的问题归结为:

我有六个文本框,它们期望值介于0和给定数字之间。 我努力实现的目标是:

  • 如果输入的数字介于0和指定数字(作为标签)之间,文本将保持黑色
  • 如果输入的数字超过指定的数字,文本将变为红色
这里的问题是,如果指定的数字是“10”,并且用户输入11,它将变为红色,这是应该的,但是,如果他们按退格键(输入的数字现在是1),数字将保持红色,这不是预期的功能-数字1应为黑色,因为它介于0和指定的数字之间

所有指定的数字现在都是硬编码的(我正在学习一门初学者课程,这只是为了增加程序的功能而做的一件有趣的事情,我还没有为每个“作业”添加类),从技术上来说,你可以输入负数,我现在不关心这个问题

这是作为特定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处理程序,它从“grpGrades”组框中获取适当的TextBox控件,并将前面提到的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
子例程的最后一部分只是注释掉的代码,也是我最初添加处理程序的方式,以防我的新方法出现问题


编辑:真的有必要否决投票吗?为什么

您的代码从不测试有效值。当当前文本框返回到有效值时,将当前文本框设置为黑色的Case-Else不会被命中。这不会发生,因为选择案例将匹配文本框的当前名称,将再次测试无效值,然后退出选择案例块。您需要为当前文本框名称的相应大小写中的有效值设置颜色。这条线可以把所有的东西都简化成一条线

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

您使用的是基于名称的选择案例,唯一的条件是如果它>10,则将前景色变成红色。但你永远不会回头。现在,在您提出case else之前,让我通知您case else将仅基于textbox.name,并且由于已找到名称,因此case else不会在此处播放


因此,当找到一个名称时,您检查值>10并设置为红色,但您不会告诉它如果该名称不>10该怎么办,因此,正如其他人所说,您没有为每个文本框处理
if
的两侧。如果颜色符合条件,则设置颜色,但不反转颜色

这是我的处理方法。这有点不同,但它将所有代码放在一起,不需要任何
大小写
代码来计算调用文本框的名称

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(文本框、十进制、布尔)
函数,它接受一个
TextBox
并安全地解析其文本,查看它是否大于
Decimal
值,如果大于则返回
True
,否则返回
False

add
是一个
操作(文本框,十进制)
,它接受
TextBox
Decimal
并添加处理程序以调用
check
根据
check
的结果将颜色设置为红色或黑色

然后,为每个
文本框
调用
add
非常简单


所有代码都是硬编码的,没有神奇的字符串检查,并且都很好地封装在form load方法中。

我投票支持你。我认为你的建议是完全正确的,你已经给出了解决问题的代码+1@Steve. 对不起,实际上我在你的帖子上显示了一个橙色的否决票,不确定我在滚动时是否点击了它,但我确实撤销了它。(我猜)。如果这就是为什么你的帖子上的向下箭头是橙色的(看起来是这样,因为现在向上箭头是橙色的),那么我不是故意这么做的。我很少投反对票,除非它完全偏离了正题。没问题@CharlesMay我只是想知道我是否已经做出了决定error@GrowingCode247-是的,lambda委托非常有用。这段代码的好处在于,如果您使用VS重构工具更改按钮的名称,那么这段代码将继续工作。依赖于
选择
/
案例
的其他代码将失败。