Как проверить, не превышена ли максимальная длина текстового поля?

Моя проблема:

Я ограничиваю текстовое поле 8 символами и показываю всплывающую подсказку, когда оно превышено (> 8), а не достигнуто (= 8). Использование функции .Maxlength не позволяет пользователю превысить 8 символов, поэтому моя функция >8 никогда не выполняется.

Если я отказываюсь от функции .Maxlength и вместо этого использую .Substring для ограничения ввода, моя функция >8 выполняется, однако поведение отличается от .Substring (сохраняются последние, а не первые 8 вводов, и я теряю звук предупреждения).

Было бы намного чище иметь возможность проверять каждый раз, когда .Maxlength превышено, не затрагивая первые 8 входных данных.

Чтобы воспроизвести:

  1. В Visual Studio в режиме конструктора перетащите текстовое поле и подсказку на новую форму.
  2. Используйте следующее как есть:

Код:

Public Class Form1
    Private Sub Textbox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
        TextBox1.MaxLength = 8
        If (Not IsNumeric(TextBox1.Text) And TextBox1.Text.Length > 0) Then
            If ToolTip1.GetToolTip(TextBox1) = "" Then
                ToolTip1.ToolTipTitle = "Input must be numeric!"
                ToolTip1.Active = True
                ToolTip1.IsBalloon = True
                ToolTip1.ToolTipIcon = ToolTipIcon.Warning
                ToolTip1.Show(vbNewLine, TextBox1, 45, -40)
            End If
        ElseIf TextBox1.Text.Length > 8 Then
            'TextBox1.Text = TextBox1.Text.Substring(0, 8)
            ToolTip1.IsBalloon = True
            ToolTip1.ToolTipTitle = "8 character maximum!"
            ToolTip1.Active = True
            ToolTip1.ToolTipIcon = ToolTipIcon.Warning
            ToolTip1.Show(vbNewLine, TextBox1, 45, -40)
        Else
            ToolTip1.Active = False
            ToolTip1.Hide(TextBox1)
        End If
    End Sub
End Class

person Clarus Dignus    schedule 23.10.2014    source источник
comment
MaxLength должно быть свойством времени разработки, поэтому вам не нужно беспокоиться о том, что пользователь превысит максимальное значение, поскольку он не сможет этого сделать.   -  person Joe Enos    schedule 23.10.2014
comment
использование ErrorProvider может сэкономить немного кода, а не создавать всевозможные подсказки   -  person Ňɏssa Pøngjǣrdenlarp    schedule 23.10.2014
comment
@JoeEnos Пользователь никогда не сможет превысить максимум, но меня попросили показать всплывающую подсказку, если пользователь попытается превысить максимум. Это связано с тем, что пользователь может не знать, почему он ограничен. Что касается вашего совета во время разработки, есть ли обратная сторона установки .MaxLength в коде?   -  person Clarus Dignus    schedule 23.10.2014
comment
В вашей логике есть изъян. Рассмотрим случай, когда пользователь вводит нечисловые символы. Сравнение TextBox1.Text.Length › 8 никогда не выполняется.   -  person γηράσκω δ' αεί πο    schedule 23.10.2014
comment
У вас, вероятно, есть самое чистое решение для того, что вы ищете, с ответом LarsTech - есть и другие способы, возможно, обработка KeyPress или KeyDown, но я думаю, что этот будет намного проще. Что касается MaxLength, свойство является постоянным, поэтому установка его в обработчике событий каждый раз была избыточной — как только вы его установили, теперь это так же, как если бы вы сделали это во время разработки — что, по-видимому, не то, что вы хотите делать в чтобы получить ожидаемое поведение.   -  person Joe Enos    schedule 23.10.2014
comment
@γηράσκωδ'αείπολλάδιδασκόμε Я только что проверил это на своем конце, и вы правы. В настоящее время я исправляю логику и сообщу об исправленном коде.   -  person Clarus Dignus    schedule 23.10.2014
comment
@JoeEnos Спасибо за разъяснение и объяснение избыточности неиспользования свойства времени разработки, и да, согласно решению LarsTech, теперь я использую .Substring вместо .Maxlength.   -  person Clarus Dignus    schedule 23.10.2014
comment
@Plutonix Поставщик ошибок выглядит многообещающе и сэкономит значительное количество кода во всем моем приложении. Я этого не знал. Я изучу это в ближайшее время.   -  person Clarus Dignus    schedule 23.10.2014
comment
@γηράσκωδ'αείπολλάδιδασκόμε Логика исправлена. Упрощенный пример с использованием окон сообщений: pastebin.com/YG2kxCDD | Полный пример использования всплывающих подсказок: pastebin.com/vJU74D7k   -  person Clarus Dignus    schedule 24.10.2014
comment
У него все еще есть проблема, когда вы вводите нечисловые символы и превышаете 8 символов. Воздушный шар переворачивается.   -  person γηράσκω δ' αεί πο    schedule 24.10.2014
comment
@γηράσκωδ'αείπολλάδιδασκόμε После дальнейшего рассмотрения единственным известным мне решением является обходной путь, который вы предоставили в аналогичном кодированном примере. Что касается кода моего предпоследнего комментария, у меня есть условие If Not IsNumeric, являющееся родительским условием для условий ›8 и ›0. В настоящее время оператор ›8 является родительским в If ToolTip1.GetToolTip(), который производит инверсию... (продолжение)...   -  person Clarus Dignus    schedule 25.10.2014
comment
@γηράσκωδ'αείπολλάδιδασκόμε ... (продолжение)... Воспитание ›8 операторов вместо ›0 операторов, родительский ›8 оператор и ›0 оператор и родительский оператор If Not IsNumeric, каждый из которых содержит If ToolTip1.GetToolTip(), предотвращает срабатывание ›8. Удаление ›0 предотвращает инверсию, но за счет ›0. Это единственные перестановки, которые я могу вообразить с тем знанием, которое у меня есть в настоящее время.   -  person Clarus Dignus    schedule 25.10.2014
comment
Вместо того, чтобы постоянно проверять TextBox1.Text.Length > 8, вы можете поместить его в начало, а затем проверить Not IsNumeric(TextBox1.Text). Вам не нужно TextBox1.Text.Length > 0. Еще кое-что. Поскольку вы все время пишете один и тот же код (показывая всплывающую подсказку), поместите его в функцию. Я приведу вам пример, который я написал в качестве ответа.   -  person γηράσκω δ' αεί πο    schedule 25.10.2014


Ответы (3)


Когда вы заменяете текст, он сбрасывает курсор, поэтому верните его на место в конце:

TextBox1.Text = TextBox1.Text.Substring(0, 8)
TextBox1.Select(TextBox1.TextLength, 0)
person LarsTech    schedule 23.10.2014
comment
Спасибо, ЛарсТек (+1). Это идеальное решение для того, чтобы заставить .Substring вести себя как .Maxlength, но что касается моей общей проблемы, мне все еще требуется обходной путь для выполнения условия ›8 для отображения всплывающей подсказки. - person Clarus Dignus; 23.10.2014
comment
@ClarusDignus Это видно в моей форме. Обязательно закомментируйте строку MaxLength. - person LarsTech; 23.10.2014
comment
Извинения. Я закомментировал неправильную строку. Еще раз спасибо. - person Clarus Dignus; 23.10.2014

Лучше подавить клавишу, если она недействительна:

Private Sub TextBox1_KeyPress(sender As System.Object, e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress
    Dim str As String

    str = TextBox1.Text
    str = str.Insert(TextBox1.SelectionStart, CStr(e.KeyChar))

    If e.KeyChar = ChrW(Keys.Back) Then
        HideToolTip()
    ElseIf str.Length > 8 Then
        ShowToolTip("8 character maximum!")

        e.Handled = True
    ElseIf Not IsNumeric(str) Then
        ShowToolTip("Input must be numeric!")

        e.Handled = True
    Else
        HideToolTip()
    End If

End Sub

Private Sub HideToolTip()
    If ToolTip1.GetToolTip(TextBox1) <> "" Then
        ToolTip1.Active = False
        ToolTip1.Hide(TextBox1)
    End If
End Sub

Private Sub ShowToolTip(ByVal str As String)
    'always check if tooltip is visible, to avoid inversion
    If ToolTip1.GetToolTip(TextBox1) = "" Then
        ToolTip1.ToolTipTitle = str
        ToolTip1.Active = True
        ToolTip1.IsBalloon = True
        ToolTip1.ToolTipIcon = ToolTipIcon.Warning
        ToolTip1.Show(vbNewLine, TextBox1, 45, -40, 1000)
    End If
End Sub

ИЗМЕНИТЬ

В функции IsNumeric() есть незначительная «ошибка», поскольку она допускает числовые значения с пробелами и множественными «.».

8..888 'is numeric
.9999  'is numeric

Чтобы решить все:

Private Sub TextBox1_KeyPress(sender As System.Object, e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress
    Dim str As String = "0123456789."

    If e.KeyChar = ChrW(Keys.Back) Then
        HideToolTip()
    ElseIf TextBox1.Text.Length = 8 Then
        ShowToolTip("8 character maximum!")

        e.Handled = True
    ElseIf e.KeyChar = "." And (TextBox1.Text.Contains(".") Or TextBox1.SelectionStart = 0) Then 'supress a second "." or a first one
        ShowToolTip("Input must be numeric!")

        e.Handled = True
    ElseIf Not str.Contains(CStr(e.KeyChar)) Then
        ShowToolTip("Input must be numeric!")

        e.Handled = True
    Else
        HideToolTip()
    End If

End Sub
person γηράσκω δ' αεί πο    schedule 25.10.2014

Добавьте это после вызова подстроки

TextBox1.SelectionStart = 8
person UnhandledExcepSean    schedule 23.10.2014