MyCheckBox.xaml.vb 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. Imports System.Windows.Markup
  2. <ContentProperty("Inlines")>
  3. Public Class MyCheckBox
  4. Implements ISettingControl
  5. '基础
  6. Public Uuid As Integer = GetUuid()
  7. ''' <summary>
  8. ''' 复选框勾选状态改变。
  9. ''' </summary>
  10. ''' <param name="user">是否为用户手动改变的勾选状态。</param>
  11. Public Event Change(sender As Object, user As Boolean)
  12. Public Event PreviewChange(sender As Object, e As RouteEventArgs)
  13. '自定义属性
  14. Public Property Checked As Boolean
  15. Get
  16. Return GetValue(CheckedProperty)
  17. End Get
  18. Set(value As Boolean)
  19. SetChecked(value, False)
  20. End Set
  21. End Property
  22. Public Shared ReadOnly CheckedProperty As DependencyProperty =
  23. DependencyProperty.Register("Checked", GetType(Boolean), GetType(MyCheckBox), New PropertyMetadata(False,
  24. Sub(d As MyCheckBox, e As DependencyPropertyChangedEventArgs)
  25. '在使用 XAML 设置 Checked 属性时,不会触发 Checked_Set 方法,所以需要在这里手动触发 UI 改变
  26. If Not d.IsLoaded Then d.SyncUI()
  27. End Sub))
  28. Private Const AnimationTimeOfCheck As Integer = 150 '勾选状态变更动画长度
  29. ''' <summary>
  30. ''' 手动设置 Checked 属性。
  31. ''' </summary>
  32. ''' <param name="value">新的 Checked 属性。</param>
  33. ''' <param name="user">是否由用户引发。</param>
  34. Public Sub SetChecked(value As Boolean, user As Boolean)
  35. Try
  36. If value = Checked Then Return
  37. 'Preview 事件
  38. If value AndAlso user Then
  39. Dim e = New RouteEventArgs(user)
  40. RaiseEvent PreviewChange(Me, e)
  41. If e.Handled Then
  42. MouseDowned = True
  43. Checkbox_MouseLeave()
  44. MouseDowned = False
  45. Return
  46. End If
  47. End If
  48. SetValue(CheckedProperty, value)
  49. If IsLoaded Then RaiseEvent Change(Me, user)
  50. '更改动画
  51. SyncUI()
  52. RaiseCustomEvent()
  53. Catch ex As Exception
  54. Log(ex, "设置 Checked 失败")
  55. End Try
  56. End Sub
  57. Private Sub SyncUI()
  58. If AniControlEnabled = 0 AndAlso IsLoaded Then '防止默认属性变更触发动画
  59. AllowMouseDown = False
  60. If Checked Then
  61. '由无变有
  62. AniStart({
  63. AaScale(ShapeBorder, 12 - ShapeBorder.Width, AnimationTimeOfCheck, , New AniEaseOutFluent, , True),
  64. AaScaleTransform(ShapeCheck, 1 - CType(ShapeCheck.RenderTransform, ScaleTransform).ScaleX, AnimationTimeOfCheck * 2, AnimationTimeOfCheck * 0.7, New AniEaseOutBack(AniEasePower.Weak)),
  65. AaScale(ShapeBorder, 6, AnimationTimeOfCheck * 2, AnimationTimeOfCheck * 0.7, New AniEaseOutBack, , True)
  66. }, "MyCheckBox Scale " & Uuid)
  67. AniStart({
  68. AaColor(ShapeBorder, Border.BorderBrushProperty, If(IsEnabled, If(IsMouseOver, "ColorBrush3", "ColorBrush2"), "ColorBrushGray5"), AnimationTimeOfCheck)
  69. }, "MyCheckBox BorderColor " & Uuid)
  70. AniStart({
  71. AaCode(Sub() AllowMouseDown = True, AnimationTimeOfCheck * 2)
  72. }, "MyCheckBox AllowMouseDown " & Uuid)
  73. Else
  74. '由有变无
  75. AniStart({
  76. AaScale(ShapeBorder, 12 - ShapeBorder.Width, AnimationTimeOfCheck, , New AniEaseOutFluent, , True),
  77. AaScaleTransform(ShapeCheck, -CType(ShapeCheck.RenderTransform, ScaleTransform).ScaleX, AnimationTimeOfCheck * 0.9, , New AniEaseInFluent(AniEasePower.Weak)),
  78. AaScale(ShapeBorder, 6, AnimationTimeOfCheck * 2, AnimationTimeOfCheck * 0.7, New AniEaseOutBack, , True)
  79. }, "MyCheckBox Scale " & Uuid)
  80. AniStart({
  81. AaColor(ShapeBorder, Border.BorderBrushProperty, If(IsEnabled, If(IsMouseOver, "ColorBrush3", "ColorBrush1"), "ColorBrushGray5"), AnimationTimeOfCheck)
  82. }, "MyCheckBox BorderColor " & Uuid)
  83. AniStart({
  84. AaCode(Sub() AllowMouseDown = True, AnimationTimeOfCheck * 2)
  85. }, "MyCheckBox AllowMouseDown " & Uuid)
  86. End If
  87. Else
  88. '不使用动画
  89. AniStop("MyCheckBox Scale " & Uuid)
  90. AniStop("MyCheckBox BorderColor " & Uuid)
  91. AniStop("MyCheckBox AllowMouseDown " & Uuid)
  92. If Checked Then
  93. CType(ShapeCheck.RenderTransform, ScaleTransform).ScaleX = 1
  94. CType(ShapeCheck.RenderTransform, ScaleTransform).ScaleY = 1
  95. ShapeBorder.SetResourceReference(Border.BorderBrushProperty, If(IsEnabled, "ColorBrush2", "ColorBrushGray5"))
  96. Else
  97. CType(ShapeCheck.RenderTransform, ScaleTransform).ScaleX = 0
  98. CType(ShapeCheck.RenderTransform, ScaleTransform).ScaleY = 0
  99. ShapeBorder.SetResourceReference(Border.BorderBrushProperty, If(IsEnabled, "ColorBrush1", "ColorBrushGray5"))
  100. End If
  101. End If
  102. End Sub
  103. Public ReadOnly Property Inlines As InlineCollection
  104. Get
  105. Return LabText.Inlines
  106. End Get
  107. End Property
  108. Public Property Text As String
  109. Get
  110. Return GetValue(TextProperty)
  111. End Get
  112. Set(value As String)
  113. SetValue(TextProperty, value)
  114. End Set
  115. End Property '内容
  116. Public Shared ReadOnly TextProperty As DependencyProperty = DependencyProperty.Register("Text", GetType(String), GetType(MyCheckBox), New PropertyMetadata(New PropertyChangedCallback(
  117. Sub(sender As DependencyObject, e As DependencyPropertyChangedEventArgs)
  118. If Not IsNothing(sender) Then CType(sender, MyCheckBox).LabText.Text = e.NewValue
  119. End Sub)))
  120. '点击事件
  121. Private MouseDowned As Boolean = False
  122. Private AllowMouseDown As Boolean = True
  123. Private Sub Checkbox_MouseUp() Handles Me.MouseLeftButtonUp
  124. If Not MouseDowned Then Return
  125. Log("[Control] 按下复选框(" & (Not Checked).ToString & "):" & Text)
  126. MouseDowned = False
  127. SetChecked(Not Checked, True)
  128. AniStart(AaColor(ShapeBorder, Border.BackgroundProperty, "ColorBrushHalfWhite", 100), "MyCheckBox Background " & Uuid)
  129. End Sub
  130. Private Sub Checkbox_MouseDown() Handles Me.MouseLeftButtonDown
  131. If Not AllowMouseDown Then Return
  132. MouseDowned = True
  133. Focus()
  134. AniStart(AaColor(ShapeBorder, Border.BackgroundProperty, "ColorBrushBg1", 100), "MyCheckBox Background " & Uuid)
  135. If Checked Then
  136. AniStart({
  137. AaScale(ShapeBorder, 16.5 - ShapeBorder.Width, 1000, , New AniEaseOutFluent(AniEasePower.Strong), Absolute:=True),
  138. AaScaleTransform(ShapeCheck, 0.9 - CType(ShapeCheck.RenderTransform, ScaleTransform).ScaleX, 1000, , New AniEaseOutFluent(AniEasePower.Strong))
  139. }, "MyCheckBox Scale " & Uuid)
  140. Else
  141. AniStart(AaScale(ShapeBorder, 16.5 - ShapeBorder.Width, 1000, , New AniEaseOutFluent(AniEasePower.Strong), Absolute:=True), "MyCheckBox Scale " & Uuid)
  142. End If
  143. End Sub
  144. Private Sub Checkbox_MouseLeave() Handles Me.MouseLeave
  145. If Not MouseDowned Then Return
  146. MouseDowned = False
  147. AniStart(AaColor(ShapeBorder, Border.BackgroundProperty, "ColorBrushHalfWhite", 100), "MyCheckBox Background " & Uuid)
  148. If Checked Then
  149. AniStart({
  150. AaScale(ShapeBorder, 18 - ShapeBorder.Width, 400, , New AniEaseOutFluent(AniEasePower.Strong), Absolute:=True),
  151. AaScaleTransform(ShapeCheck, 1 - CType(ShapeCheck.RenderTransform, ScaleTransform).ScaleX, 500, , New AniEaseOutFluent(AniEasePower.Strong))
  152. }, "MyCheckBox Scale " & Uuid)
  153. Else
  154. AniStart(AaScale(ShapeBorder, 18 - ShapeBorder.Width, 400, , New AniEaseOutFluent(AniEasePower.Strong), Absolute:=True), "MyCheckBox Scale " & Uuid)
  155. End If
  156. End Sub
  157. '指向动画
  158. Private Const AnimationTimeOfMouseIn As Integer = 100
  159. Private Const AnimationTimeOfMouseOut As Integer = 200
  160. Private Sub Checkbox_IsEnabledChanged() Handles Me.IsEnabledChanged
  161. If IsLoaded AndAlso AniControlEnabled = 0 Then '防止默认属性变更触发动画
  162. '有动画
  163. If IsEnabled Then
  164. '可用
  165. Checkbox_MouseLeaveAnimation()
  166. Else
  167. '不可用
  168. AniStart({
  169. AaColor(ShapeBorder, Border.BorderBrushProperty, ColorGray5 - ShapeBorder.BorderBrush, AnimationTimeOfMouseOut)
  170. }, "MyCheckBox BorderColor " & Uuid)
  171. AniStart({
  172. AaColor(LabText, TextBlock.ForegroundProperty, ColorGray5 - LabText.Foreground, AnimationTimeOfMouseOut)
  173. }, "MyCheckBox TextColor " & Uuid)
  174. End If
  175. Else
  176. '无动画
  177. AniStop("MyCheckBox TextColor " & Uuid)
  178. AniStop("MyCheckBox BorderColor " & Uuid)
  179. LabText.SetResourceReference(TextBlock.ForegroundProperty, If(Me.IsEnabled, "ColorBrush1", "ColorBrushGray5"))
  180. ShapeBorder.SetResourceReference(Border.BorderBrushProperty, If(Me.IsEnabled, If(Checked, "ColorBrush2", "ColorBrush1"), "ColorBrushGray5"))
  181. End If
  182. End Sub
  183. Private Sub Checkbox_MouseEnterAnimation() Handles Me.MouseEnter
  184. AniStart({
  185. AaColor(LabText, TextBlock.ForegroundProperty, "ColorBrush3", AnimationTimeOfMouseIn)
  186. }, "MyCheckBox TextColor " & Uuid)
  187. AniStart({
  188. AaColor(ShapeBorder, Border.BorderBrushProperty, "ColorBrush3", AnimationTimeOfMouseIn)
  189. }, "MyCheckBox BorderColor " & Uuid)
  190. End Sub
  191. Private Sub Checkbox_MouseLeaveAnimation() Handles Me.MouseLeave
  192. If Not IsEnabled Then Return 'MouseLeave 比 IsEnabledChanged 后执行,所以如果自定义事件修改了 IsEnabled,将导致显示错误
  193. AniStart({
  194. AaColor(LabText, TextBlock.ForegroundProperty, If(Me.IsEnabled, "ColorBrush1", "ColorBrushGray5"), AnimationTimeOfMouseOut)
  195. }, "MyCheckBox TextColor " & Uuid)
  196. AniStart({
  197. AaColor(ShapeBorder, Border.BorderBrushProperty, If(Me.IsEnabled, If(Checked, "ColorBrush2", "ColorBrush1"), "ColorBrushGray5"), AnimationTimeOfMouseOut)
  198. }, "MyCheckBox BorderColor " & Uuid)
  199. End Sub
  200. #Region "设置"
  201. Private Sub RefreshSetting(NewValue As String) Implements ISettingControl.RefreshSetting
  202. Checked = Boolean.Parse(NewValue)
  203. End Sub
  204. Private Function GetCurrentSetting() As String Implements ISettingControl.GetCurrentSetting
  205. Return Checked.ToString
  206. End Function
  207. Private Sub SaveSetting() Handles Me.Change
  208. SettingService.SaveSetting(Me)
  209. End Sub
  210. #End Region
  211. End Class