I needed to Limit several TextBoxes in my WPF MVVM application to only allow Numeric Characters.
I stumbles upon a very useful post by Jermey Likeness which described a method using Attached Behaviours, which worked well for me;
http://csharperimage.jeremylikness.com/2009/10/silverlight-behaviors-and-triggers_07.html
I modified this code slightly to allow for Decimal point control also.
The VB.net Code is as follows;
Imports System.Collections.ObjectModelNamespace BehavioursPublic Class clsTextBoxFilters
#Region "Variables"
Private Shared ReadOnly _controlKeys As List(Of Key) = New List(Of Key) From {Key.Back,
Key.CapsLock,
Key.LeftCtrl,
Key.RightCtrl,
Key.Down,
                                                                                            Key.[End],Key.Enter,
Key.Escape,
Key.Home,
Key.Insert,
Key.Left,
Key.PageDown,
Key.PageUp,
Key.Right,
Key.LeftShift,
Key.RightShift,
Key.Tab,
Key.Up,
                                                                                            Key.Decimal,Key.OemPeriod}
#End Region#Region "Helper Functions"
        ''' <summary>        ''' Check if the key is a Numeric        ''' </summary>        ''' <param name="key__1"></param>        ''' <returns></returns>        ''' <remarks></remarks>Private Shared Function _IsDigit(key__1 As Key) As Boolean
Dim shiftKey As Boolean = (Keyboard.Modifiers And ModifierKeys.Shift) <> 0
Dim retVal As Boolean
If key__1 >= Key.D0 AndAlso key__1 <= Key.D9 AndAlso Not shiftKey Then
                retVal = True            Else                retVal = key__1 >= Key.NumPad0 AndAlso key__1 <= Key.NumPad9End If
            Return retValEnd Function
#End Region#Region "Getters and Setters"
        ''' <summary>        ''' Get the value of the Numeric Filter Dependancy Property        ''' </summary>        ''' <param name="src"></param>        ''' <returns></returns>        ''' <remarks></remarks>Public Shared Function GetIsPositiveNumericFilter(src As DependencyObject) As Boolean
Return CBool(src.GetValue(IsPositiveNumericFilterProperty))
End Function
        ''' <summary>        ''' Set the Value of the Numeric Filter Dependancy Property        ''' </summary>        ''' <param name="src"></param>        ''' <param name="value"></param>        ''' <remarks></remarks>Public Shared Sub SetIsPositiveNumericFilter(src As DependencyObject, value As Boolean)
src.SetValue(IsPositiveNumericFilterProperty, value)
End Sub
        ''' <summary>        ''' Get the Value of the IsIntegerOnly Dependancy Property        ''' </summary>        ''' <param name="src"></param>        ''' <returns></returns>        ''' <remarks></remarks>Public Shared Function GetIsIntegerOnly(src As DependencyObject) As Boolean
Return CBool(src.GetValue(IsIntegerOnlyProperty))
End Function
        ''' <summary>        ''' Sets the Value of the IsIntegerOnly Dependancy Property        ''' </summary>        ''' <param name="src"></param>        ''' <param name="value"></param>        ''' <remarks></remarks>Public Shared Sub SetIsIntegerOnly(src As DependencyObject, value As Boolean)
src.SetValue(IsIntegerOnlyProperty, value)
End Sub
#End Region#Region "Dependancy Properties"
Public Shared IsPositiveNumericFilterProperty As DependencyProperty = DependencyProperty.RegisterAttached("IsPositiveNumericFilter", GetType(Boolean), GetType(clsTextBoxFilters), New PropertyMetadata(False, AddressOf IsPositiveNumericFilterChanged))
Public Shared IsIntegerOnlyProperty As DependencyProperty = DependencyProperty.Register("IsIntegerOnly", GetType(Boolean), GetType(clsTextBoxFilters), Nothing)
#End Region#Region "Dependancy Property Change Handlers"
        ''' <summary>        ''' Determines if the Behaviour is active, adds the KeyDown event Handler        ''' </summary>        ''' <param name="src"></param>        ''' <param name="args"></param>        ''' <remarks></remarks>Public Shared Sub IsPositiveNumericFilterChanged(src As DependencyObject, args As DependencyPropertyChangedEventArgs)
If src IsNot Nothing AndAlso TypeOf src Is TextBox Then
Dim textBox As TextBox = TryCast(src, TextBox)
If CBool(args.NewValue) Then
AddHandler textBox.KeyDown, AddressOf _TextBoxPositiveNumericKeyDown
End If
End If
End Sub
#End Region#Region "Event Handlers"
        ''' <summary>        ''' KeyDown event... Check if the Key is valid... If so allow, if not then ignore the key        ''' </summary>        ''' <param name="sender"></param>        ''' <param name="e"></param>        ''' <remarks></remarks>Private Shared Sub _TextBoxPositiveNumericKeyDown(sender As Object, e As KeyEventArgs)
Dim handled As Boolean = True
Dim txtSender As TextBox = DirectCast(sender, TextBox)
If e.Key = Key.OemPeriod Then 'Is the current key a Decimal Point?
If txtSender.GetValue(IsIntegerOnlyProperty) = True Then 'Is this an Integer Only TextBox?
                    handled = TrueElseIf InStr(txtSender.Text, ".") = 0 And Len(txtSender.Text) > 0 Then 'We only want 1 decimal point, and it can't be the first digit!
                    handled = FalseElse 'Otherwise ignore the keypress
                    handled = TrueEnd If
ElseIf _controlKeys.Contains(e.Key) OrElse _IsDigit(e.Key) Then 'Is the Key a numeric or an allowed key?
                handled = FalseEnd If
e.Handled = handled
End Sub
#End RegionEnd Class
End NamespaceThe XAML to add to the UserControl Header Namespaces is;
xmlns:Behaviors="clr-namespace:CriticalPath_WPF_MVVM_EF.Behaviours"The XAML to add to the TextBox Is;
Behaviors:clsTextBoxFilters.IsPositiveNumericFilter="True" Behaviors:clsTextBoxFilters.IsIntegerOnly="True"
Very handy!
 
 
No comments:
Post a Comment