Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VB

Textbox Regular Expression Validation

4.17/5 (4 votes)
15 Dec 2014CPOL2 min read 21.3K  
An extension to the textbox control to offer textbox validation without the need to constantly apply code using regular expressions.

Introduction

This extension allows you to add validation functionality to a textbox without having to re-write on the OnKeyPress commands over and over again. Also, it captures the WndProc for pasting into the textbox and makes sure that the pasted text matches that of the current validation mode.

You have 8 new properties that cover Regular Expression and Empty Field properties (Empty string)

  • Regex_LiveExpression - This property is readonly, it displays the current Regular Expression being used.
  • Regex_Mode - Select the mode you want to use, Any, Numbers Only, AlphaNumeric, Custom
    • NumbersOnly - Uses [0-9]
    • AlphaNumeric - Uses [0-9a-zA-Z]
    • Custom - Uses the Custom Expression you enter into the Regex_CustomRegEx Property
  • Regex_CustomRegEx - Enter your regular expression here (works in Conjuction with Regex_Mode)
  • Regex_AllowPaste - Uses the Custom Expression you enter into the Regex_CustomRegEx Property
  • Regex_AllowPeriods - Use this to supercede all regular expression for (dot) period entry, usually used with NumbersOnly Regex_Mode to allow double types (111.222)
  • AllowBlank - This property determines if to allow the field to become empty
  • AllowBlankDefaultValue - if the property becomes empty and AllowBlank is false, the value will be entered into the textbox to avoid empty fields, save messy text validations for large number of numeri/currency fields so you could enter 0.00 as your default value, then... no need to code loads of validations as it is already done for you.
  • AllowBlankWarningMessage - This property, if not blank, will set a messagebox to the user with what ever text is here.  If the property is left blank it will not display a message.

The great thing about this is that you can set the regular expression by textbox without having to rebuild a new class through the properties so you could set to 'Text Only' and enter the regular expression for say 'Email' address, etc. I built this because I hate having to rewrite keypress events.

Using the Code

On your project, add a new class and add this code into the new class, then rebuild your project/solution.

You will now see RegExTextbox appear in the top right of your toolbox.

VB.NET
' *********************************
' Required Imports
' *********************************
Imports System.Windows.Forms
Imports System.Drawing
Imports System.Text.RegularExpressions
Imports System.ComponentModel

<ToolboxBitmap(GetType(RegExTextbox), "RegEx.bmp")> Partial Public Class RegExTextbox
    Inherits TextBox
#Region "Regex Modes Properties"
    ''' <summary>
    ''' Enumeration for the RegEx Mode Property.
    ''' </summary>
    ''' <remarks></remarks>
    Public Enum RegexMode
        None = 0
        NumbersOnly = 1
        AlphaNumeric = 2
        Custom = 3
    End Enum

    Private _prvRegex_Mode As RegexMode = RegexMode.None
    Private _prvRegex_AllowPeriod As Boolean = True
    Private _prvRegex_AllowPeriodRegex As String = "|[.]"
    Private _prvRegex_NumbersOnly As String = "[0-9]"
    Private _prvRegex_AlphaNumeric As String = "[0-9a-zA-Z]"
    Private _prvRegex_CustomRegex As String = ""
    Private _prvRegex_CTRLKeyDown As Boolean = False
    Private _prvRegex_AllowPaste As Boolean = True

    <Description("Determine which Regular Expression Mode to use")> _
    Public Property Regex_Mode As RegexMode
        Get
            Return _prvRegex_Mode
        End Get
        Set(value As RegexMode)
            _prvRegex_Mode = value
        End Set
    End Property
    <Description("The current expression that is being used by the control")> _
    Public ReadOnly Property Regex_LiveExpression As String
        Get
            Dim tmpReturn As String
            Select Case _prvRegex_Mode
                Case RegexMode.NumbersOnly : tmpReturn = _prvRegex_NumbersOnly
                Case RegexMode.AlphaNumeric : tmpReturn = _prvRegex_AlphaNumeric
                Case RegexMode.Custom : tmpReturn = _prvRegex_CustomRegex
                Case Else : tmpReturn = ""
            End Select
            Return tmpReturn & IIf(String.IsNullOrEmpty(tmpReturn), String.Empty, IIf(Regex_AllowPeriods = True, _prvRegex_AllowPeriodRegex, String.Empty))
        End Get
    End Property
    <Description("If Regex_Mode is Custom, the control will use the regular expression entered here.")> _
    Public Property Regex_CustomRegEx As String
        Get
            Return _prvRegex_CustomRegex
        End Get
        Set(value As String)
            _prvRegex_CustomRegex = value
        End Set
    End Property
    <Description("A boolean to determine if 'Periods' (dot) are allowed - this will overwrite in custom mode")> _
    Public Property Regex_AllowPeriods As Boolean
        Get
            Return _prvRegex_AllowPeriod
        End Get
        Set(value As Boolean)
            _prvRegex_AllowPeriod = value
        End Set
    End Property
    <Description("Allow Pasting into the Textbox, When a user pastes into the field it will use the current RegexMode")> _
    Public Property Regex_AllowPaste As Boolean
        Get
            Return _prvRegex_AllowPaste
        End Get
        Set(value As Boolean)
            _prvRegex_AllowPaste = value
        End Set
    End Property
#End Region
#Region "Blank Textbox Properties"
    Private _prvBlankAllow As Boolean = True
    Private _prvBlankDefaultVal As String = "0"
    Private _prvBlankWarningMessage As String = ""

    <Description("Determines if the field is allowed to be blank, See also AllowBlankDefaultValue/AllowBlankWarningMessage ")> _
    Public Property AllowBlank As Boolean
        Get
            Return _prvBlankAllow
        End Get
        Set(value As Boolean)
            _prvBlankAllow = value
        End Set
    End Property

    <Description("The default value to replace with if the control is empty")> _
    Public Property AllowBlankDefaultValue As String
        Get
            Return _prvBlankDefaultVal
        End Get
        Set(value As String)
            If (Len(value) = 0) Then
                MsgBox("Allow Blank default value cannot be null, setting to 0", vbCritical + vbOKOnly, "Property Cannot be Null")
                _prvBlankDefaultVal = "0"
            Else
                _prvBlankDefaultVal = value
            End If

        End Set
    End Property
    <Description("The message to be displayed if ther user deletes all the text [Optional] Leave blank for no message")> _
    Public Property AllowBlankWarningMessage As String
        Get
            Return _prvBlankWarningMessage
        End Get
        Set(value As String)
            _prvBlankWarningMessage = value
        End Set
    End Property
#End Region

    Protected Overrides Sub OnKeyDown(e As System.Windows.Forms.KeyEventArgs)
        ' *********************************
        ' Determine if Control Key is Pressed
        ' *********************************
        If (e.Control) Then _prvRegex_CTRLKeyDown = True
        MyBase.OnKeyDown(e)
    End Sub
    Protected Overrides Sub OnKeyUp(e As System.Windows.Forms.KeyEventArgs)
        ' *********************************
        ' Determine if Control Key is Released
        ' *********************************
        If (e.Control) Then _prvRegex_CTRLKeyDown = False
        MyBase.OnKeyDown(e)

    End Sub
    Protected Overrides Sub OnKeyPress(e As System.Windows.Forms.KeyPressEventArgs)

        ' *********************************
        ' Check if the Regex Mode is set to anything but 'None'
        ' *********************************
        If (_prvRegex_Mode <> RegexMode.None) Then

            ' *********************************
            ' Is the Control Key Pressed
            ' *********************************
            If (_prvRegex_CTRLKeyDown = True) Then
                'Skip Past if we are using CTRL Key - Only concern is CTRL+V being handled below
            Else
                ' *********************************
                'Determine Which Regular Expression To use based on the RegexMode
                '   If Numbers Only Then Use _prvRegex_NumbersOnly
                '   Elseif AlphaNumeric Then Use _prvRegex_AphaNumeric
                '   Else Use _prvRegex_CustomRegex
                'Then perform the Regex Match and check if Count = 0 - If 0 then Prevent Characters
                ' *********************************
                If ((Regex.Match(e.KeyChar, Regex_LiveExpression).Captures.Count = 0) And (Not e.KeyChar = Chr(8))) Then
                    e.Handled = True
                End If

            End If 'End of if Control key is pressed

        End If 'End of check for RegexMode = None

        ' *********************************
        ' Continue with KeyPressEvents if use has set extra in code.
        ' *********************************
        MyBase.OnKeyPress(e)
    End Sub
    Protected Overrides Sub OnTextChanged(e As System.EventArgs)

        ' *********************************
        ' Check if Blank field is allowed
        ' *********************************
        If (AllowBlank = False) Then

            ' *********************************
            ' Check if Lenght is 0 - if so - replace with Default Value
            ' *********************************
            If (Me.TextLength = 0) Then Me.Text = AllowBlankDefaultValue

            If (Len(AllowBlankWarningMessage) > 0) Then
                MsgBox(AllowBlankWarningMessage, vbOKOnly, "Text Validation Error")
            End If
        End If
        MyBase.OnTextChanged(e)
    End Sub

#Region "Paste Handling"
    Private Const WM_PASTE As Integer = &H302
    ' *********************************
    ' Handle Paste Events
    ' *********************************
    Protected Overrides Sub WndProc(ByRef m As Message)

        If m.Msg = WM_PASTE AndAlso _prvRegex_AllowPaste = True AndAlso Clipboard.ContainsText Then
            ' *********************************
            ' RegEx the Clipboard Text if mode
            ' is not set to none
            ' *********************************
            If (_prvRegex_Mode <> RegexMode.None) Then
                'Blank String Var for parsing the clipboard text
                Dim str_Clipboard As String = ""

                ' *********************************
                ' Loop through matches and add to str_clipboard
                ' *********************************
                For Each regMatch As Match In Regex.Matches(Clipboard.GetText, Regex_LiveExpression)
                    str_Clipboard &= regMatch.Value
                Next
                ' *********************************
                ' Set the clipboard text if str_clipboard is not null/empty
                ' Throws exception if string is null/empty
                ' *********************************
                If Not (String.IsNullOrEmpty(str_Clipboard)) Then
                    Dim tmpCBD As String = Clipboard.GetText

                    Clipboard.SetText(str_Clipboard)
                    MyBase.WndProc(m)
                Else
                    'Dont do anything
                End If 'End of Check if Clipboard is Null/Empty

            End If 'End of check for RegexMode = None
        Else
            ' *********************************
            ' Continue with Windows Message
            ' *********************************
            MyBase.WndProc(m)
        End If 'End of check if is Paste message/Paste Allowed/Clipboard contains text
    End Sub
#End Region

End Class

Points of Interest

Nothing to report but I will be happy to get any comments / suggestions.

History

  • 15th December, 2014: Initial upload
  • 16th December, 2014: Added functionality for Null Value handling
    • Added functionality for null value handling (set to default value if string length is 0)
    • Improved code
      • Better Commentry
      • Descriptions for property boxes
      • Improve handling of WndProc for Paste
      • Better RegEx handling on Paste

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)