''' <summary>
''' Extends the texbox with the Decimal and / or Integer validation
''' And provides users with Value and ValueInt properties that return
''' validated decimal or integer values.
''' </summary>
''' <remarks>
''' * To turn off decimal validation turn ValidateIntOnly
''' property to True (default is false).
''' * To prevent user from changing focus with not validated input set
''' the CancelValidationOnFail property to True (default is false).
''' * To Get the decimal value use the Value property.
''' * To Get the integer value use the ValueInt property.
''' </remarks>
Class NumericTextbox
Inherits TextBox
'Private members
Private _Validated As Boolean = False
Private _IntOnly As Boolean = True
Private _ShouldCancelValidattion As Boolean = False
Private _TreatEmptyAsZero As Boolean = True
Private _Value As Decimal
Private _IntValue As Integer
Private _NotValidatedBackColor As Color = Color.Pink
Private _ValidatedBackColor As Color = Color.PaleGreen
''' <summary>
''' Occurs between Validating and Validated events if the validation failed.
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Public Event NotValidated(ByVal sender As Object, ByVal e As System.EventArgs)
Public Sub New()
MyBase.New()
MyBase.CausesValidation = True
End Sub
Public Overrides Property Multiline() As Boolean
Get
Return MyBase.Multiline
End Get
Set(ByVal value As Boolean)
If value Then
Throw New NotSupportedException("Multiline mode is not supported")
End If
End Set
End Property
''' <summary>
''' Gets or sets the setting indicating whether the control should treat an empty string as zero. Default is True.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property TreatEmptyAsZero() As Boolean
Get
Return _TreatEmptyAsZero
End Get
Set(ByVal v As Boolean)
_TreatEmptyAsZero = v
Call Me.OnTextChanged(Nothing)
End Set
End Property
''' <summary>
''' Gets or sets the background of the control when the value is not validated.
''' </summary>
''' <remarks>Overrides the BackGound property. the default value is Color.Pink</remarks>
Public Property NotValidatedBackColor() As Color
Get
Return _NotValidatedBackColor
End Get
Set(ByVal v As Color)
_NotValidatedBackColor = v
MyBase.BackColor = v
MyBase.Invalidate()
End Set
End Property
''' <summary>
''' Gets or sets the backgound of the control when the value has been validated.
''' </summary>
''' <remarks>The default value is Color.PaleGreen</remarks>
Public Property ValidatedBackColor() As Color
Get
Return _ValidatedBackColor
End Get
Set(ByVal v As Color)
_ValidatedBackColor = v
MyBase.BackColor = v
MyBase.Invalidate()
End Set
End Property
''' <summary>
''' Turns off Decimal validation and validates integers only.
''' ''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks>Value property will return a rounded decimal.
''' To get an integer value use <see cref="ValueInt">ValueInt property</see>.</remarks>
Public Property ValidateIntOnly() As Boolean
Get
Return _IntOnly
End Get
Set(ByVal v As Boolean)
_IntOnly = v
End Set
End Property
''' <summary>
''' Gets a decimal value of the validated user input.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks>Read only</remarks>
Public ReadOnly Property Value() As Decimal
Get
Return _Value
End Get
End Property
''' <summary>
''' Gets an integer values of the valdated user input.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks>To get the decimal value use <see cref="Value">Value property</see></remarks>
Public ReadOnly Property ValueInt() As Integer
Get
If Not _IntOnly Then
Throw New InvalidOperationException("ValidateIntOnly property is set to false. Set it to true to turn on the integer evaluation.")
Exit Property
End If
Return _IntValue
End Get
End Property
''' <summary>
''' Gets or sets a setting indicating whether the control should cancel validation of a control.
''' ''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks>When set the control won't allow to change focus if the input value is in the wrong formst.</remarks>
Public Property CancelValidationOnFail() As Boolean
Get
Return _ShouldCancelValidattion
End Get
Set(ByVal v As Boolean)
_ShouldCancelValidattion = v
End Set
End Property
''' <summary>
''' Raises Validating event or cancels Validation if CancelValidationOnFail property is set to true
''' </summary>
''' <param name="e"></param>
''' <remarks></remarks>
Protected Overrides Sub OnValidating(ByVal e As System.ComponentModel.CancelEventArgs)
If ValidateValue() Then
MyBase.OnValidating(e)
Else
e.Cancel = _ShouldCancelValidattion
MyBase.OnValidating(e)
RaiseEvent NotValidated(Me, New System.EventArgs)
End If
End Sub
Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
If ValidateValue() Then
Me.BackColor = _ValidatedBackColor
Else
Me.BackColor = _NotValidatedBackColor
End If
MyBase.OnTextChanged(e)
Me.Invalidate()
End Sub
Protected Overridable Function ValidateValue() As Boolean
' Allows any format to be converted to decimal
Dim ValidationText As String = MyBase.Text
' Check whether we should trean an empty string as zero
If MyBase.Text.Length = 0 AndAlso Me._TreatEmptyAsZero Then ValidationText = "0"
Dim fp As IFormatProvider = System.Globalization.NumberFormatInfo.InvariantInfo
If Not _IntOnly Then
Return Decimal.TryParse(ValidationText, System.Globalization.NumberStyles.Any, fp, _Value)
Else
Return Integer.TryParse(ValidationText, System.Globalization.NumberStyles.Integer, fp, _IntValue)
_Value = CDec(_IntValue)
End If
End Function
End Class