2016-02-02 2 views
-1

Моя проблема сводится к следующему:VB - TextChanged не срабатывает должным образом после нажатия клавиши backspace?

У меня есть шесть текстовых полей, которые ожидают значения от 0 до заданного числа. То, что я пытаюсь достичь:

  • Если введенное число находится в пределах от 0 до заданного числа (в качестве метки), то текст будет оставаться черным
  • Если введенное число превышает заданное число, то текст краснеют

проблема здесь состоит в том, что, если указанное число «10», и пользователь вводит 11, он становится красным, как и положено, ОДНАКО, если они попали в клавишу возврата (вошел в число теперь 1) номер остается красным, что не является предполагаемой функциональностью - номер 1 должен быть черным, так как он находится между 0 и указанным номером nu mber.

Все указанные цифры сейчас жестко закодированы (я нахожусь в новичке, и это просто то, что я делаю для удовольствия, чтобы увеличить функциональность программы, и я не получил добавления классов для каждого «Присвоения»), и вы можете вводить отрицательные числа с технической точки зрения, на данный момент меня это не волнует.

Это подпрограмма, которая добавляется в качестве обработчика для всех текстовых полей в пределах определенного 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 обработчик, который получает соответствующие элементы управления TextBox из «grpGrades» 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 

Последняя часть подпрограммы просто закомментировать код и как я изначально был добавлены обработчики, на всяком случае, что-то пошло не так с моим новым методом.

РЕДАКТИРОВАТЬ: Было ли это серьезно необходимо для downvote? По какой причине?

ответ

4

Ваш код никогда не проверяет допустимое значение. Case Else, который устанавливает текущее текстовое поле на черный, никогда не попадает, когда текущее текстовое поле возвращается к допустимому значению. Этого не может быть, потому что Select Case будет соответствовать текущему имени текстового поля, будет снова проверяться на недопустимое значение и затем выходит из блока Select 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. Извините, на самом деле я показывал оранжевый нисходящий поток на вашем посту, не уверен, ударил ли я его при прокрутке, но я отменил его. (Я предполагаю). Если это причина, то стрелка вниз на вашем посту была оранжевой (и это выглядит так, потому что теперь стрелка вверх оранжевая), тогда я не намеренно делал это. Я редко опускаюсь вниз, если это просто что-то совсем не в основе. –

+0

Без проблем @CharlesMay Мне просто интересно, если я сделал ошибку – Steve

1

Вы с помощью выбора случая на основе имени и единственным условием является то, что если это> 10 затем включите ForeColor красный. Но ты никогда не возвращаешь его обратно. Теперь, прежде чем вы откроете дело еще, позвольте мне сообщить вам, что случай else будет основываться только на текстовом поле. И поскольку имя найдено, случай, в который еще не пришел, играет здесь.

так, если имя найдено, то проверьте значение> 10 и установить красный, но вы не говорите ему, что делать, если это не> 10

+0

Gotcha, спасибо! – 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 

Так, check является Func(Of TextBox, Decimal, Boolean), который принимает TextBox и безопасно разбирает свой текст, чтобы увидеть, если она больше, чем значение Decimal и возвращает True если это и False иначе.

И add является Action(Of TextBox, Decimal), который принимает TextBox и Decimal и добавляет обработчик для вызова check установить цвет на красный или черный на основе результата check.

Это очень просто позвонить add за каждого TextBox.

Все жестко закодированные без проверок цепочки магов и все красиво инкапсулированы в режиме загрузки формы.

+0

Пришло время узнать о делегатах vb. Спасибо! – GrowingCode247

+0

@ GrowingCode247 - Да, делегаты лямбды чрезвычайно полезны. Очень приятная вещь в этом коде: если вы измените имя кнопок с помощью инструментов рефакторинга VS, этот код будет продолжать работать. Другой код, который опирается на 'Select' /' Case', потерпит неудачу. – Enigmativity

+1

Очень тонкое решение – Steve

Смежные вопросы