| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- Public Class MyTextBox
- Inherits TextBox
- Implements ISettingControl
- '自定义属性
- Public Property HasBackground As Boolean = True
- Public Property ShowValidateResult As Boolean = True
- Public Property CornerRadius As CornerRadius
- Get
- Return GetValue(CornerRadiusProperty)
- End Get
- Set(value As CornerRadius)
- SetValue(CornerRadiusProperty, value)
- End Set
- End Property
- Public Shared ReadOnly CornerRadiusProperty As DependencyProperty =
- DependencyProperty.Register("CornerRadius", GetType(CornerRadius), GetType(MyTextBox), New PropertyMetadata(New CornerRadius(3)))
- '额外控件初始化
- Private _labWrong As TextBlock = Nothing
- Private ReadOnly Property labWrong As TextBlock
- Get
- If Template Is Nothing Then Return Nothing
- If _labWrong Is Nothing Then _labWrong = Template.FindName("labWrong", Me)
- Return _labWrong
- End Get
- End Property
- Private _labHint As TextBlock = Nothing
- Private ReadOnly Property labHint As TextBlock
- Get
- If Template Is Nothing Then Return Nothing
- If _labHint Is Nothing Then _labHint = Template.FindName("labHint", Me)
- Return _labHint
- End Get
- End Property
- Public Overrides Sub OnApplyTemplate()
- MyBase.OnApplyTemplate()
- If HintText = "" OrElse labHint.Text <> "" Then Return
- labHint.Text = If(Text = "", HintText, "")
- End Sub
- '事件
- Public Uuid As Integer = GetUuid()
- Public Shared Event ValidateChanged(sender As Object, e As EventArgs)
- Private _ChangedEventList As List(Of RoutedEventHandler)
- Public ReadOnly Property ChangedEventList As List(Of RoutedEventHandler)
- Get
- If _ChangedEventList Is Nothing Then _ChangedEventList = New List(Of RoutedEventHandler)
- Return _ChangedEventList
- End Get
- End Property
- Public Custom Event ValidatedTextChanged As RoutedEventHandler
- AddHandler(value As RoutedEventHandler)
- ChangedEventList.Add(value)
- End AddHandler
- RemoveHandler(value As RoutedEventHandler)
- ChangedEventList.Remove(value)
- End RemoveHandler
- RaiseEvent(sender As Object, e As TextChangedEventArgs)
- For Each handler As RoutedEventHandler In ChangedEventList
- If Not IsNothing(handler) Then handler.Invoke(sender, e)
- Next
- End RaiseEvent
- End Event
- '输入验证
- ''' <summary>
- ''' 输入验证结果。若为空字符串则无错误,否则为第一个错误原因。
- ''' </summary>
- Public Property ValidateResult As String
- Get
- Return GetValue(ValidateResultProperty)
- End Get
- Set(value As String)
- SetValue(ValidateResultProperty, value)
- End Set
- End Property
- Public Shared ReadOnly ValidateResultProperty As DependencyProperty =
- DependencyProperty.Register("ValidateResult", GetType(String), GetType(MyTextBox), New PropertyMetadata("",
- Sub(d As MyTextBox, e As DependencyPropertyChangedEventArgs)
- d.SetValue(IsValidatedPropertyKey, String.IsNullOrEmpty(e.NewValue))
- End Sub))
- ''' <summary>
- ''' 是否通过了输入验证。
- ''' </summary>
- Public ReadOnly Property IsValidated As Boolean
- Get
- Return GetValue(IsValidatedProperty)
- End Get
- End Property
- Private Shared ReadOnly IsValidatedPropertyKey As DependencyPropertyKey =
- DependencyProperty.RegisterReadOnly("IsValidated", GetType(Boolean), GetType(MyTextBox), New PropertyMetadata(True))
- Public Shared ReadOnly IsValidatedProperty As DependencyProperty = IsValidatedPropertyKey.DependencyProperty
- ''' <summary>
- ''' 输入验证的规则。
- ''' </summary>
- Public Property ValidateRules As ObjectModel.Collection(Of Validate)
- Get
- Return _ValidateRules
- End Get
- Set(Value As ObjectModel.Collection(Of Validate))
- _ValidateRules = Value
- Validate()
- End Set
- End Property
- Private _ValidateRules As New ObjectModel.Collection(Of Validate)
- ''' <summary>
- ''' 进行输入验证。
- ''' </summary>
- Public Sub Validate() Handles Me.Loaded
- '执行输入验证
- ValidateResult = ModValidate.Validate(Text, ValidateRules)
- '根据结果改变样式
- If ShownValidateResult <> If(IsValidated, ValidateState.Success, ValidateState.FailedAndShowDetail) Then
- If IsLoaded AndAlso labWrong IsNot Nothing Then
- ChangeValidateResult(IsValidated, True)
- Else
- RunInNewThread(
- Sub()
- Thread.Sleep(30)
- RunInUi(Sub() ChangeValidateResult(IsValidated, False))
- End Sub, "DelayedValidate Change")
- End If
- End If
- '更新错误信息
- If ShowValidateResult AndAlso Not IsValidated Then
- If IsLoaded AndAlso labWrong IsNot Nothing Then
- labWrong.Text = ValidateResult
- Else
- RunInNewThread(
- Sub()
- Dim IsFinished As Boolean = False
- Do Until IsFinished
- Thread.Sleep(20)
- RunInUiWait(
- Sub()
- If labWrong IsNot Nothing Then
- labWrong.Text = ValidateResult
- IsFinished = True
- End If
- If Not IsLoaded Then IsFinished = True
- End Sub)
- Loop
- End Sub, "DelayedValidate Text")
- End If
- End If
- End Sub
- ''' <summary>
- ''' 强制显示结果为正常,类似尚未输入过文本的状态。不影响实际的检查结果。
- ''' </summary>
- Public Sub ForceShowAsSuccess()
- IsTextChanged = False
- ChangeValidateResult(IsValidated, True)
- End Sub
- Private ShownValidateResult As ValidateState = ValidateState.NotInited
- Private Sub ChangeValidateResult(IsSuccessful As Boolean, IsLoaded As Boolean)
- If IsLoaded AndAlso AniControlEnabled = 0 AndAlso labWrong IsNot Nothing Then
- If IsSuccessful OrElse Not IsTextChanged Then
- '变为正确
- ShownValidateResult = If(IsSuccessful, ValidateState.Success, ValidateState.FailedButTextNotChanged)
- AniStart({
- AaOpacity(labWrong, -labWrong.Opacity, 150),
- AaHeight(labWrong, -labWrong.Height, 150,, New AniEaseOutFluent),
- AaCode(Sub() labWrong.Visibility = Visibility.Collapsed,, True)
- }, "MyTextBox Validate " & Uuid)
- ElseIf ShowValidateResult Then
- '变为错误
- ShownValidateResult = ValidateState.FailedAndShowDetail
- labWrong.Visibility = Visibility.Visible
- AniStart({
- AaOpacity(labWrong, 1 - labWrong.Opacity, 150),
- AaHeight(labWrong, 21 - labWrong.Height, 150,, New AniEaseOutFluent)
- }, "MyTextBox Validate " & Uuid)
- Else
- '变为错误,但不显示文本
- ShownValidateResult = ValidateState.FailedAndHideDetail
- End If
- Else
- ShownValidateResult = ValidateState.NotLoaded
- End If
- RefreshColor()
- RaiseEvent ValidateChanged(Me, New EventArgs)
- End Sub
- Private Enum ValidateState
- NotInited
- Success
- FailedButTextNotChanged
- FailedAndShowDetail
- FailedAndHideDetail
- NotLoaded
- End Enum
- '提示文本
- ''' <summary>
- ''' 是否已经由用户输入过文本,若尚未输入过,则不显示输入检查的失败。
- ''' </summary>
- Private IsTextChanged As Boolean = False
- Public Property HintText As String
- Get
- Return GetValue(HintTextProperty)
- End Get
- Set(value As String)
- SetValue(HintTextProperty, value)
- End Set
- End Property
- Public Shared ReadOnly HintTextProperty As DependencyProperty =
- DependencyProperty.Register("HintText", GetType(String), GetType(MyTextBox), New PropertyMetadata("",
- Sub(t As MyTextBox, e As DependencyPropertyChangedEventArgs)
- If t.labHint IsNot Nothing Then t.labHint.Text = If(t.Text = "", t.HintText, "")
- End Sub))
- Private Sub MyTextBox_TextChanged(sender As MyTextBox, e As TextChangedEventArgs) Handles Me.TextChanged
- Try
- '改变提示文本
- If labHint IsNot Nothing Then labHint.Text = If(Text = "", HintText, "")
- '改变输入记录
- IsTextChanged = IsLoaded
- '进行输入验证
- Validate()
- If Not IsValidated Then Return
- '改变文本
- RaiseEvent ValidatedTextChanged(sender, e)
- Catch ex As Exception
- Log(ex, "进行输入验证时出错", NotifyLevel.MsgBoxAndFeedback)
- End Try
- End Sub
- '颜色
- Private Sub RefreshColor() Handles Me.IsEnabledChanged, Me.MouseEnter, Me.MouseLeave, Me.GotFocus, Me.LostFocus
- Try
- '不对 ComboBox 从属进行动画
- If TemplatedParent IsNot Nothing AndAlso TypeOf TemplatedParent Is MyComboBox Then Return
- '判断当前颜色
- Dim ForeColorName As String, BackColorName As String
- Dim AnimationTime As Integer
- If IsEnabled Then
- If IsValidated OrElse Not IsTextChanged Then
- If IsFocused Then
- ForeColorName = "ColorBrush3"
- BackColorName = "ColorBrush7"
- AnimationTime = 10
- ElseIf IsMouseOver Then
- ForeColorName = "ColorBrush4"
- BackColorName = "ColorBrush7"
- AnimationTime = 100
- Else '未选中
- ForeColorName = "ColorBrushBg0"
- BackColorName = "ColorBrushHalfWhite"
- AnimationTime = 100
- End If
- Else
- ForeColorName = "ColorBrushRedLight"
- BackColorName = "ColorBrushRedBack"
- AnimationTime = 200
- End If
- Else
- ForeColorName = "ColorBrushGray5"
- BackColorName = "ColorBrushGray6"
- AnimationTime = 200
- End If
- If Not HasBackground Then BackColorName = "ColorBrushTransparent"
- '触发颜色动画
- If IsLoaded AndAlso AniControlEnabled = 0 Then '防止默认属性变更触发动画
- '有动画
- AniStart({
- AaColor(Me, BorderBrushProperty, ForeColorName, AnimationTime),
- AaColor(Me, BackgroundProperty, BackColorName, AnimationTime)
- }, "MyTextBox Color " & Uuid)
- Else
- '无动画
- AniStop("MyTextBox Color " & Uuid)
- SetResourceReference(BorderBrushProperty, ForeColorName)
- SetResourceReference(BackgroundProperty, BackColorName)
- End If
- Catch ex As Exception
- Log(ex, "文本框颜色改变出错")
- End Try
- End Sub
- Private Sub RefreshTextColor() Handles Me.IsEnabledChanged
- Dim NewColor As MyColor = If(IsEnabled, ColorGray1, ColorGray4)
- If CType(Foreground, SolidColorBrush).Color.R = NewColor.R Then Return
- If IsLoaded AndAlso AniControlEnabled = 0 AndAlso Not Text = "" Then
- '有动画
- AniStart({AaColor(Me, ForegroundProperty, If(IsEnabled, "ColorBrushGray1", "ColorBrushGray4"), 200)}, "MyTextBox TextColor " & Uuid)
- Else
- '无动画
- AniStop("MyTextBox TextColor " & Uuid)
- Foreground = NewColor
- End If
- End Sub
- '在按下回车时触发自定义事件
- Private Sub MyTextBox_KeyUp(sender As Object, e As KeyEventArgs) Handles Me.KeyUp
- If e.Key = Key.Enter Then RaiseCustomEvent()
- End Sub
- #Region "设置"
- Private Sub RefreshSetting(NewValue As String) Implements ISettingControl.RefreshSetting
- Text = NewValue
- End Sub
- Private Function GetCurrentSetting() As String Implements ISettingControl.GetCurrentSetting
- Return Text
- End Function
- Private Sub SaveSetting() Handles Me.ValidatedTextChanged
- SettingService.SaveSetting(Me)
- End Sub
- #End Region
- End Class
|