我有一个附加的行为问题。当我将行为附加到我的文本框时,我失去了所有基本功能,例如最大长度?这是我将它附加到我的 xaml 中的方式。当我取消附加行为时,最大长度工作,当我把它放回去时它不起作用?任何帮助将不胜感激!
这是我正在使用的课程
导入 System.Windows 导入 System.Windows.Controls 导入 System.Globalization
命名空间附加行为
Public Class TextBoxMaskBehavior
Inherits DependencyObject
区域“最小值属性”
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
结束区域
区域“最大值属性”
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
结束区域
区域“面具属性”
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
结束区域
区域“私有静态方法”
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 Class
Public Enum MaskType
Any
[Integer]
[Decimal]
End Enum
结束命名空间