I have a attached behavior issue. When I attach the behavior to my textbox I lose all my base functionality like the Max length? Here is how I am attaching it in my xaml. When I take off the attached behavior the max length work when I put it back on it doesnt work? Any help would be greatly appreciated!
This is the class I am using
Imports System.Windows Imports System.Windows.Controls Imports System.Globalization
Namespace AttachedBehaviours
Public Class TextBoxMaskBehavior
Inherits DependencyObject
Region "MinimumValue Property"
Public Shared Function GetMinimumValue(ByVal obj As DependencyObject) As Double
Return CDbl(obj.GetValue(MinimumValueProperty))
End Function
Public Shared Sub SetMinimumValue(ByVal obj As DependencyObject, ByVal value As Double)
obj.SetValue(MinimumValueProperty, value)
End Sub
Public Shared ReadOnly MinimumValueProperty As DependencyProperty = DependencyProperty.RegisterAttached("MinimumValue", GetType(Double), GetType(TextBoxMaskBehavior), New FrameworkPropertyMetadata(Double.NaN, AddressOf MinimumValueChangedCallback))
Private Shared Sub MinimumValueChangedCallback(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
Dim _this As TextBox = TryCast(d, TextBox)
ValidateTextBox(_this)
End Sub
End Region
Region "MaximumValue Property"
Public Shared Function GetMaximumValue(ByVal obj As DependencyObject) As Double
Return CDbl(obj.GetValue(MaximumValueProperty))
End Function
Public Shared Sub SetMaximumValue(ByVal obj As DependencyObject, ByVal value As Double)
obj.SetValue(MaximumValueProperty, value)
End Sub
Public Shared ReadOnly MaximumValueProperty As DependencyProperty = DependencyProperty.RegisterAttached("MaximumValue", GetType(Double), GetType(TextBoxMaskBehavior), New FrameworkPropertyMetadata(Double.NaN, AddressOf MaximumValueChangedCallback))
Private Shared Sub MaximumValueChangedCallback(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
Dim _this As TextBox = TryCast(d, TextBox)
ValidateTextBox(_this)
End Sub
End Region
Region "Mask Property"
Public Shared Function GetMask(ByVal obj As DependencyObject) As MaskType
Return CType(obj.GetValue(MaskProperty), MaskType)
End Function
Public Shared Sub SetMask(ByVal obj As DependencyObject, ByVal value As MaskType)
obj.SetValue(MaskProperty, value)
End Sub
Public Shared ReadOnly MaskProperty As DependencyProperty = DependencyProperty.RegisterAttached("Mask", GetType(MaskType), GetType(TextBoxMaskBehavior), New FrameworkPropertyMetadata(AddressOf MaskChangedCallback))
Private Shared Sub MaskChangedCallback(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
If TypeOf e.OldValue Is TextBox Then
RemoveHandler TryCast(e.OldValue, TextBox).PreviewTextInput, AddressOf TextBox_PreviewTextInput
DataObject.RemovePastingHandler(TryCast(e.OldValue, TextBox), DirectCast(AddressOf TextBoxPastingEventHandler, DataObjectPastingEventHandler))
End If
Dim _this As TextBox = TryCast(d, TextBox)
If _this Is Nothing Then
Return
End If
If CType(e.NewValue, MaskType) <> MaskType.Any Then
AddHandler _this.PreviewTextInput, AddressOf TextBox_PreviewTextInput
DataObject.AddPastingHandler(_this, DirectCast(AddressOf TextBoxPastingEventHandler, DataObjectPastingEventHandler))
End If
ValidateTextBox(_this)
End Sub
End Region
Region "Private Static Methods"
Private Shared Sub ValidateTextBox(ByVal _this As TextBox)
If GetMask(_this) <> MaskType.Any Then
_this.Text = ValidateValue(GetMask(_this), _this.Text, GetMinimumValue(_this), GetMaximumValue(_this))
End If
End Sub
Private Shared Sub TextBoxPastingEventHandler(ByVal sender As Object, ByVal e As DataObjectPastingEventArgs)
Dim _this As TextBox = TryCast(sender, TextBox)
Dim clipboard As String = TryCast(e.DataObject.GetData(GetType(String)), String)
clipboard = ValidateValue(GetMask(_this), clipboard, GetMinimumValue(_this), GetMaximumValue(_this))
If Not String.IsNullOrEmpty(clipboard) Then
_this.Text = clipboard
End If
e.CancelCommand()
e.Handled = True
End Sub
Private Shared Sub TextBox_PreviewTextInput(ByVal sender As Object, ByVal e As System.Windows.Input.TextCompositionEventArgs)
Dim _this As TextBox = TryCast(sender, TextBox)
Dim isValid As Boolean = IsSymbolValid(GetMask(_this), e.Text)
e.Handled = Not isValid
If isValid Then
Dim caret As Integer = _this.CaretIndex
Dim text As String = _this.Text
Dim textInserted As Boolean = False
Dim selectionLength As Integer = 0
If _this.SelectionLength > 0 Then
text = text.Substring(0, _this.SelectionStart) & text.Substring(_this.SelectionStart + _this.SelectionLength)
caret = _this.SelectionStart
End If
If e.Text = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator Then
While True
Dim ind As Integer = text.IndexOf(NumberFormatInfo.CurrentInfo.NumberDecimalSeparator)
If ind = -1 Then
Exit While
End If
text = text.Substring(0, ind) & text.Substring(ind + 1)
If caret > ind Then
caret -= 1
End If
End While
If caret = 0 Then
text = "0" & text
caret += 1
Else
If caret = 1 AndAlso String.Empty & text(0) = NumberFormatInfo.CurrentInfo.NegativeSign Then
text = NumberFormatInfo.CurrentInfo.NegativeSign & "0" & text.Substring(1)
caret += 1
End If
End If
If caret = text.Length Then
selectionLength = 1
textInserted = True
text = text & NumberFormatInfo.CurrentInfo.NumberDecimalSeparator & "0"
caret += 1
End If
ElseIf e.Text = NumberFormatInfo.CurrentInfo.NegativeSign Then
textInserted = True
If _this.Text.Contains(NumberFormatInfo.CurrentInfo.NegativeSign) Then
text = text.Replace(NumberFormatInfo.CurrentInfo.NegativeSign, String.Empty)
If caret <> 0 Then
caret -= 1
End If
Else
text = NumberFormatInfo.CurrentInfo.NegativeSign + _this.Text
caret += 1
End If
End If
If Not textInserted Then
text = text.Substring(0, caret) & Convert.ToString(e.Text) & (If((caret < _this.Text.Length), text.Substring(caret), String.Empty))
caret += 1
End If
Try
Dim val As Double = Convert.ToDouble(text)
Dim newVal As Double = ValidateLimits(GetMinimumValue(_this), GetMaximumValue(_this), val)
If val <> newVal Then
text = newVal.ToString()
ElseIf val = 0 Then
If Not text.Contains(NumberFormatInfo.CurrentInfo.NumberDecimalSeparator) Then
text = "0"
End If
End If
Catch
text = "0"
End Try
While text.Length > 1 AndAlso text(0) = "0"c AndAlso String.Empty & text(1) <> NumberFormatInfo.CurrentInfo.NumberDecimalSeparator
text = text.Substring(1)
If caret > 0 Then
caret -= 1
End If
End While
While text.Length > 2 AndAlso String.Empty & text(0) = NumberFormatInfo.CurrentInfo.NegativeSign AndAlso text(1) = "0"c AndAlso String.Empty & text(2) <> NumberFormatInfo.CurrentInfo.NumberDecimalSeparator
text = NumberFormatInfo.CurrentInfo.NegativeSign & text.Substring(2)
If caret > 1 Then
caret -= 1
End If
End While
If caret > text.Length Then
caret = text.Length
End If
_this.Text = text
_this.CaretIndex = caret
_this.SelectionStart = caret
_this.SelectionLength = selectionLength
e.Handled = True
End If
End Sub
Private Shared Function ValidateValue(ByVal mask As MaskType, ByVal value As String, ByVal min As Double, ByVal max As Double) As String
If String.IsNullOrEmpty(value) Then
Return String.Empty
End If
value = value.Trim()
Select Case mask
Case MaskType.[Integer]
Try
Convert.ToInt64(value)
Return value
Catch
End Try
Return String.Empty
Case MaskType.[Decimal]
Try
Convert.ToDouble(value)
Return value
Catch
End Try
Return String.Empty
End Select
Return value
End Function
Private Shared Function ValidateLimits(ByVal min As Double, ByVal max As Double, ByVal value As Double) As Double
If Not min.Equals(Double.NaN) Then
If value < min Then
Return min
End If
End If
If Not max.Equals(Double.NaN) Then
If value > max Then
Return max
End If
End If
Return value
End Function
Private Shared Function IsSymbolValid(ByVal mask As MaskType, ByVal str As String) As Boolean
Select Case mask
Case MaskType.Any
Return True
Case MaskType.[Integer]
If str = NumberFormatInfo.CurrentInfo.NegativeSign Then
Return True
End If
Exit Select
Case MaskType.[Decimal]
If str = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator OrElse str = NumberFormatInfo.CurrentInfo.NegativeSign Then
Return True
End If
Exit Select
End Select
If mask.Equals(MaskType.[Integer]) OrElse mask.Equals(MaskType.[Decimal]) Then
For Each ch As Char In str
If Not [Char].IsDigit(ch) Then
Return False
End If
Next
Return True
End If
Return False
End Function
End Region
End Class
Public Enum MaskType
Any
[Integer]
[Decimal]
End Enum
End Namespace