Reputation: 8736
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
Reputation: 8736
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
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