Home
Search
 
What's New
Index
Books
Links
Q & A
Newsletter
Banners
 
Feedback
Tip Jar
 
C# Helper...
 
XML RSS Feed
Follow VBHelper on Twitter
 
 
 
MSDN Visual Basic Community
 
 
 
 
 
 
TitleMake an ExtenderProvider to validate TextBoxes containing integers within a range in VB .NET
DescriptionThis example shows how to make an ExtenderProvider to validate TextBoxes containing integers within a range in VB .NET. The provider catches its clients' Validating events and verifies that the values are integers within a specified range.
KeywordsExtenderProvider, integer range, range, validation, validate
CategoriesSoftware Engineering, Controls, VB.NET
 
See Tutorial: Introduction to ExtenderProviders in VB .NET for an overview of creating ExtenderProviders.

This provider stores MinValue, MaxValue, and RangeFieldName values for each of its clients in its private RangeInfo class. It stores RangeInfo objects in its m_RangeInfo hashtable. It also adds an event handler to catch each client control's Validating event.

When that event fires, the provider's ValidateTextBox subroutine determines whether the client TextBox contains a value that is an integer within the desired range. If the TextBox doesn't contain the right value, it assigns an error to the TextBox using the provider's embedded ErrorProvider component.

The GetRangeInfo helper function returns a control's RangeInfo object or a default object it the control doesn't have an entry.

The AddOrRemoveIfNecessary helper routine compares a RangeInfo object to a default object. If the object has the default values, then the routine ensures that it is removed from the m_RangeInfo hashtable. If the object does not hold the default values, then the routine ensures that it is in the hashtable.

Finally, to help the program decide whether it is safe to exit, the provider includes a HasError function. This function validates all of the registered client controls to display errors for any that are out of range. It then moves focus to the one with the smallest TabIndex value and displays that control's error message in a message box.

 
Imports System.ComponentModel
Imports System.Text.RegularExpressions

<ToolboxBitmap(GetType(IntegerRangeProvider), _
    "integer_range_provider.bmp"), _
 ProvideProperty("MinValue", GetType(Control)), _
 ProvideProperty("MaxValue", GetType(Control)), _
 ProvideProperty("RangeFieldName", GetType(Control))> _
Public Class IntegerRangeProvider
    Inherits System.ComponentModel.Component
    Implements IExtenderProvider

... Component Designer generated code ...

    ' Information about a control's range.
    Private Class RangeInfo
        Public MinValue As Integer
        Public MaxValue As Integer
        Public RangeFieldName As String
        
        Public Sub New()
            MinValue = Integer.MinValue
            MaxValue = Integer.MaxValue
            RangeFieldName = Nothing
        End Sub

        ' Return True if this object represents no range.
        Public Function IsDefault() As Boolean
            Return (MinValue = Integer.MinValue) And _
                   (MaxValue = Integer.MaxValue) And _
                   (RangeFieldName Is Nothing)
        End Function
    End Class

    ' The information about fields with ranges.
    Private m_RangeInfo As New Hashtable

    Private m_Enabled As Boolean = True
    <Category("Behavior"), _
     DefaultValue(True)> _
    Public Property Enabled() As Boolean
        Get
            Return m_Enabled
        End Get
        Set(ByVal Value As Boolean)
            m_Enabled = Value
        End Set
    End Property

    ' We can extend TextBoxes.
    Public Function CanExtend(ByVal client_control As _
        Object) As Boolean Implements _
        IExtenderProvider.CanExtend
        Return (TypeOf client_control Is TextBox)
    End Function

    ' Return this control's minimum value.
    <Category("Validation"), _
     DefaultValue(Integer.MinValue)> _
    Public Function GetMinValue(ByVal client_control As _
        Control) As Integer
        Return GetRangeInfo(client_control).MinValue
    End Function

    ' Set this control's minimum value.
    <Category("Validation"), _
     DefaultValue(Integer.MinValue)> _
    Public Sub SetMinValue(ByVal client_control As Control, _
        ByVal min_value As Integer)
        ' Get this control's range info.
        Dim range_info As RangeInfo = _
            GetRangeInfo(client_control)

        ' Set the new minimum value.
        range_info.MinValue = min_value

        ' Add or remove the RangeInfo if necessary.
        AddOrRemoveIfNecessary(client_control, range_info)
    End Sub

    ' Return this control's maximum value.
    <Category("Validation"), _
     DefaultValue(Integer.MaxValue)> _
    Public Function GetMaxValue(ByVal client_control As _
        Control) As Integer
        Return GetRangeInfo(client_control).MaxValue
    End Function

    ' Set this control's maximum value.
    <Category("Validation"), _
     DefaultValue(Integer.MaxValue)> _
    Public Sub SetMaxValue(ByVal client_control As Control, _
        ByVal max_value As Integer)
        ' Get this control's range info.
        Dim range_info As RangeInfo = _
            GetRangeInfo(client_control)

        ' Set the new minimum value.
        range_info.MaxValue = max_value

        ' Add or remove the RangeInfo if necessary.
        AddOrRemoveIfNecessary(client_control, range_info)
    End Sub

    ' Return this control's error message.
    <Category("Validation"), _
     DefaultValue("")> _
    Public Function GetRangeFieldName(ByVal client_control _
        As Control) As String
        Return GetRangeInfo(client_control).RangeFieldName
    End Function

    ' Set this control's error message.
    <Category("Validation"), _
     DefaultValue("")> _
    Public Sub SetRangeFieldName(ByVal client_control As _
        Control, ByVal error_message As String)
        ' Get this control's range info.
        Dim range_info As RangeInfo = _
            GetRangeInfo(client_control)

        ' Set the new minimum value.
        range_info.RangeFieldName = error_message

        ' Add or remove the RangeInfo if necessary.
        AddOrRemoveIfNecessary(client_control, range_info)
    End Sub

    ' A client is validating. See if it is blank.
    Private Sub Client_Validating(ByVal sender As Object, _
        ByVal e As System.ComponentModel.CancelEventArgs)
        If Not m_Enabled Then Exit Sub
        ValidateTextBox(DirectCast(sender, TextBox))
    End Sub

    ' Validate the TextBox.
    Private Sub ValidateTextBox(ByVal client_control As _
        TextBox)
        ' Get the control's text.
        Dim client_text As String = client_control.Text
        Dim range_info As RangeInfo = _
            GetRangeInfo(client_control)

        ' See if the text satisfies the range.
        If client_text.Length = 0 Then
            ' It's blank. Allow it.
            errOutOfRange.SetError(client_control, "")
        Else
            ' See if it looks like an integer.
            Dim r As New Regex("^(-|)[0-9]+$")
            If r.Match(client_text).Success Then
                ' It looks like an integer. Get its value.
                Try
                    Dim client_value As Integer = _
                        Integer.Parse(client_text)
                    If client_value < range_info.MinValue _
                        Then
                        ' Too small.
                        errOutOfRange.SetError(client_control, _
                            "Field " & _
                            range_info.RangeFieldName & " " & _
                            "must be no smaller than " & _
                            range_info.MinValue.ToString)
                    ElseIf client_value > _
                        range_info.MaxValue Then
                        ' Too big.
                        errOutOfRange.SetError(client_control, _
                            "Field " & _
                            range_info.RangeFieldName & " " & _
                            "must be no greater than " & _
                            range_info.MaxValue.ToString)
                    Else
                        ' Just right.
                        errOutOfRange.SetError(client_control, _
                            "")
                    End If
                Catch ex As Exception
                    ' Something weird is going on. Possibly
                    ' this
                    ' value has too many digits for an
                    ' integer.
                    ' Display a generic "bad integer"
                    ' message.
                    errOutOfRange.SetError(client_control, _
                        "Field " & _
                        range_info.RangeFieldName & " must " & _
                        "be an integer")
                End Try
            Else
                ' It doesn't look like an integer.
                ' Complain.
                errOutOfRange.SetError(client_control, _
                    "Field " & range_info.RangeFieldName & _
                    " must be an integer")
            End If
        End If
    End Sub

    ' Return this control's RangeInfo.
    Private Function GetRangeInfo(ByVal client_control As _
        Control) As RangeInfo
        ' See if we have RangeInfo for this control.
        If m_RangeInfo.Contains(client_control) Then
            ' We have RangeInfo for this control. Return it.
            Return DirectCast(m_RangeInfo(client_control), _
                RangeInfo)
        Else
            ' We do not have RangeInfo for this control.
            ' Return a new default RangeInfo.
            Return New RangeInfo
        End If
    End Function

    ' Add or remove this RangeInfo if necessary.
    Private Sub AddOrRemoveIfNecessary(ByVal client_control _
        As Control, ByVal range_info As RangeInfo)
        ' See if the RangeInfo should be present but is not,
        ' or should not be present but is.
        If range_info.IsDefault <> Not _
            m_RangeInfo.Contains(client_control) Then
            If range_info.IsDefault Then
                ' The RangeInfo should not be present but
                ' is.
                m_RangeInfo.Remove(client_control)
                RemoveHandler client_control.Validating, _
                    AddressOf Client_Validating
            Else
                ' The RangeInfo should be present but is
                ' not.
                m_RangeInfo.Add(client_control, range_info)
                AddHandler client_control.Validating, _
                    AddressOf Client_Validating
            End If
        End If
    End Sub

    ' If some control has an error, display its error
    ' message,
    ' set focus to it, and return True. If all controls are
    ' okay, then return False.
    Public Function HasError() As Boolean
        If Not m_Enabled Then Return False

        ' Make sure all controls have been validated.
        Dim first_text_box As TextBox = Nothing
        Dim first_tab_index As Integer = Integer.MaxValue
        For Each text_box As TextBox In m_RangeInfo.Keys
            ' Validate the TextBox.
            ValidateTextBox(text_box)

            ' See if this is the first in the tab order so
            ' far.
            If errOutOfRange.GetError(text_box).Length > 0 _
                Then
                If text_box.TabIndex < first_tab_index Then
                    first_text_box = text_box
                    first_tab_index = text_box.TabIndex
                End If
            End If
        Next text_box

        ' See if any control has an error.
        If Not (first_text_box Is Nothing) Then
            first_text_box.Focus()
            MessageBox.Show(errOutOfRange.GetError(first_text_box))
            Return True
        End If

        Return False
    End Function
End Class
 
At design time, you set the properties for TextBoxes that you want to be required. The main program doesn't need to use any code to validate TextBoxes.

If you want to ensure that all TextBoxes are valid, call the HasError function in the form's Closing event handler to see if it is safe to close the form.

 
Private Sub Form1_Closing(ByVal sender As Object, ByVal e _
    As System.ComponentModel.CancelEventArgs) Handles _
    MyBase.Closing
    e.Cancel = IntegerRangeProvider1.HasError()
End Sub

Private Sub btnOk_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles btnOk.Click
    Me.Close()
End Sub

Private Sub btnCancel_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles btnCancel.Click
    IntegerRangeProvider1.Enabled = False
    Me.Close()
End Sub
 
 
Copyright © 1997-2010 Rocky Mountain Computer Consulting, Inc.   All rights reserved.
  Updated