Mojtaba Rezaeian
Mojtaba Rezaeian

Reputation: 8736

validate strings using a regular expression while typing

I want to define a RegEx validator function which checks every character while typing (and not only after entering whole string) based on a defined RegEx:

Public Class RegExValidator
    Inherits System.Windows.Forms.TextBox

    Private regex As New System.Text.RegularExpressions.Regex("[1-9-]\/[1-9-][\-+][abo][\/]some\-number\:\d{1,5}")

    Public Function CheckUserInput(ByVal input As String) As Boolean
        ' this only checks whole input so for 
        'beggining parts of input it returns 
        'false and protects users to finish
        'their correct input
        If regex.IsMatch(input) Then
            Return True
        Else
            ' should check if currect input is matching 
            'beggining parts of RegEx and if not matches
            'some part of RegEx return false
            'else return true
        End If
    End Function

    ' I'm going to override PreProccessMessage() 
    'on real application but this is just a
    'sample to demonstrate my problem simply
    Protected Overrides Sub OnTextChanged(e As EventArgs)
        MyBase.OnTextChanged(e)
        If Not CheckUserInput(Me.Text) Then
            MsgBox("Validation failed! This character is not allowed!")
            Me.Text = Me.old_text
        End If
    End Sub

    Private old_text As String
    Public Overrides Property Text As String
        Get
            Return MyBase.Text
        End Get
        Set(value As String)
            Me.old_text = Me.Text
            MyBase.Text = value
        End Set
    End Property

End Class

Upvotes: 0

Views: 608

Answers (2)

Mojtaba Rezaeian
Mojtaba Rezaeian

Reputation: 8736

Trick: Use sample strings to complete input before testing

I used a trick to do this and my trick is to use some sample strings (each string should demonstrate a different occasion of regex matches) as complement and before testing a match if input length is not enough to rich accepting match use sample string to complete input temporary to test if it can match afterwards or it not.

Here is simplified example of what I mean but in my real project my sample is an array for supporting more complexity in regex (should test if input matches any of the samples and return false if not match any of them):

' sample should match the regular expression
Private Const sample As String = "1/1+a/some-number:6"

Public Function check_partial_match(ByVal input As String) as boolean
    If input.Length >= sample.Length Then
        Return False
    End If
    Dim teststr As String = sample.Remove(0, input.Length)
    teststr = input & teststr
    Return regex.IsMatch(teststr)
End Function

Upvotes: 1

Lucas Trzesniewski
Lucas Trzesniewski

Reputation: 51330

Disclaimer: I'm the author of PCRE.NET.

What you're asking for is called partial matching - that is, matching a partial input against a pattern.

Unfortunately, the .NET regex engine doesn't support that out of the box. You may succeed by modifying your pattern, but it gets cumbersome quickly and won't be easy in the general case.

Fortunately, this feature is provided by the PCRE library, which you can use through my PCRE.NET wrapper.

So you install the package:

Install-Package PCRE.NET

And then you use the PcreRegex class instead of Regex. You need to use one of these options: PcreMatchOptions.PartialSoft or PcreMatchOptions.PartialHard.

PCRE's docs for partial matching (which I encourage you to read) say the following:

The difference between the two options is whether or not a partial match is preferred to an alternative complete match, though the details differ between the two types of matching function.

So you choose which one best fits your needs.

Your code could look something like this:

Imports PCRE
Private regex As New PcreRegex("^[1-9-]/[1-9-][-+][abo]/some-number:\d{1,5}$")

Public Function CheckUserInput(ByVal input As String) As Boolean
    Dim match = regex.Match(input, PcreMatchOptions.PartialSoft)

    If match.Success Then
        ' The input is valid
        Return True
    ElseIf match.IsPartialMatch Then
        ' The input is valid so far, but there's still a required part missing
        Return True
    Else
        ' The input is NOT valid
        Return False
    End If
End Function

match.Success indicates a full match, whereas match.IsPartialMatch indicates an insufficient but partially valid input. Note that I enclosed your pattern in ^ and $ anchors to disallow additional unexpected input.

Note that PCRE and .NET flavors are slightly different, but the basic features are the same. You can compare them here.

Upvotes: 2

Related Questions