2016-02-02 36 views
-1

我的問題歸結爲:VB-TextChanged在退格鍵被擊中後沒有正確觸發?

我有六個文本框,期望值介於0和給定的數字之間。 我想實現的是:

  • 如果輸入的數字是0和指定的號碼(如標籤)之間,如果數字輸入的文本將保持黑色
  • 超過指定數量,文字會變成紅色

這裏的問題是,如果指定的號碼爲「10」,用戶輸入11,則會變成紅色,因爲它應該,但是,如果他們打退格鍵(輸入的號碼現在是1)數字保持紅色,這不是預期的功能 - 數字1應該是黑色的,因爲它在0和指定的nu之間MBER。

現在所有指定的數字都是硬編碼的(我在初學者課程中,這只是我爲了增加程序功能而做的一些事情,而且我還沒有添加類對於每個「任務」),你可以在技術上輸入負數,我現在不關心。

這是被添加作爲處理程序的所有文本框的特定組框內的子程序

' 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 

子程序的最後一部分只是註釋掉的代碼是怎麼原本的處理程序添加,以防萬一出事了與我的新方法。

編輯:是否真的有必要downvote?是什麼原因?

回答

4

您的代碼從不測試有效值。當前文本框返回到有效值時,將當前文本框設置爲黑色的「案例否決」不會被命中。這不會發生,因爲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

我投了票。我認爲你提出的建議是完全有效的,你已經提供瞭解決問題的代碼。 +1 – Enigmativity

+1

@Steve。對不起,實際上我在你的帖子上顯示了一個橙色downvote,不確定是否在滾動時點擊它,但我已經撤消它。 (我假設)。如果這是你的帖子上的向下箭頭是橙色的原因(因爲現在向上的箭頭是橙色,所以看起來是這樣的),那麼我並沒有故意這麼做。除非它完全脫離基地,否則我很少會冷靜下來。 –

+0

沒問題@CharlesMay我只是想知道我是否犯了一個錯誤 – Steve

1

您正在使用基於名稱和唯一的條件選擇的情況是,如果它> 10然後把前景色爲紅色。但你永遠不會退縮。現在,在你提出案例之前,讓我告訴你,其他情況只會基於textbox.name,並且因爲找到了名字,否則其他人不會在這裏玩。

因此,當一個名字找到你檢查值> 10,並設置紅色,但你不知道它做什麼,如果它不是> 10

+0

哎呀,謝謝! – GrowingCode247

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 

所以,checkFunc(Of TextBox, Decimal, Boolean),需要一個TextBox和安全解析其文本,看它是否比Decimal值,並返回True如果是和False否則。

而且addAction(Of TextBox, Decimal),需要一個TextBoxDecimal,並增加了處理程序調用check設置顏色爲紅色或黑色的基礎上check結果。

然後,對於每個TextBox,調用add非常簡單。

所有硬編碼沒有魔法字符串檢查,都很好地封裝在窗體加載方法中。

+0

有時間瞭解vb代表。謝謝! – GrowingCode247

+0

@ GrowingCode247 - 是的,lambda代表非常有用。關於這個代碼的真正好處是,如果你使用VS重構工具改變按鈕的名字,那麼這個代碼將繼續工作。依賴於'Select' /'Case'的其他代碼將會失敗。 – Enigmativity

+1

非常好的解決方案 – Steve