0

我有一个附加的行为问题。当我将行为附加到我的文本框时,我失去了所有基本功能,例如最大长度?这是我将它附加到我的 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

结束命名空间

4

1 回答 1

0

想出了解决办法。我正在测试文本的长度并确保它小于最大长度。

If Not textInserted Then If _this.Text.Length < _this.MaxLength Then text = text.Substring(0, caret) & Convert.ToString(e.Text) & (If((caret < _this.Text.Length), text.子字符串(插入符号),String.Empty))

                    caret += 1
                End If

            End If

在整数函数上使用它。

于 2010-09-30T13:20:54.080 回答