MyRadioButton.xaml.vb 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. Imports System.Windows.Markup
  2. <ContentProperty("Inlines")>
  3. Public Class MyRadioButton
  4. '基础
  5. Public Uuid As Integer = GetUuid()
  6. Public Event Check(sender As Object, raiseByMouse As Boolean)
  7. '自定义属性
  8. Public Property Logo As String
  9. Get
  10. Return ShapeLogo.Data.ToString
  11. End Get
  12. Set(value As String)
  13. ShapeLogo.Data = (New GeometryConverter).ConvertFromString(value)
  14. End Set
  15. End Property
  16. Private _LogoScale As Double = 1
  17. Public Property LogoScale() As Double
  18. Get
  19. Return _LogoScale
  20. End Get
  21. Set(value As Double)
  22. _LogoScale = value
  23. If Not IsNothing(ShapeLogo) Then ShapeLogo.RenderTransform = New ScaleTransform With {.ScaleX = LogoScale, .ScaleY = LogoScale}
  24. End Set
  25. End Property
  26. Private _Checked As Boolean = False '是否选中
  27. Public Property Checked As Boolean
  28. Get
  29. Return _Checked
  30. End Get
  31. Set(value As Boolean)
  32. SetChecked(value, False, True)
  33. End Set
  34. End Property
  35. ''' <summary>
  36. ''' 手动设置 Checked 属性。
  37. ''' </summary>
  38. ''' <param name="value">新的 Checked 属性。</param>
  39. ''' <param name="raiseByMouse">是否由用户引发。</param>
  40. ''' <param name="anime">是否执行动画。</param>
  41. Public Sub SetChecked(value As Boolean, raiseByMouse As Boolean, anime As Boolean)
  42. Try
  43. '自定义属性基础
  44. Dim IsChanged As Boolean = False
  45. If _Checked <> value Then
  46. _Checked = value
  47. IsChanged = True
  48. End If
  49. '保证只有一个单选框选中
  50. If Parent Is Nothing Then Return
  51. Dim RadioboxList As New List(Of MyRadioButton)
  52. Dim CheckedCount As Integer = 0
  53. '收集控件列表与选中个数
  54. For Each Control In CType(Parent, Object).Children
  55. If TypeOf Control Is MyRadioButton Then
  56. RadioboxList.Add(Control)
  57. If Control.Checked Then CheckedCount += 1
  58. End If
  59. Next
  60. '判断选中情况
  61. Select Case CheckedCount
  62. Case 0
  63. '没有任何单选框被选中,选择第一个
  64. RadioboxList(0).Checked = True
  65. Case Is > 1
  66. '选中项目多于 1 个
  67. If Me.Checked Then
  68. '如果本控件选中,则取消其他所有控件的选中
  69. For Each Control As MyRadioButton In RadioboxList
  70. If Control.Checked AndAlso Not Control.Equals(Me) Then Control.Checked = False
  71. Next
  72. Else
  73. '如果本控件未选中,则只保留第一个选中的控件
  74. Dim FirstChecked = False
  75. For Each Control As MyRadioButton In RadioboxList
  76. If Control.Checked Then
  77. If FirstChecked Then
  78. Control.Checked = False '修改 Checked 会自动触发 Change 事件,所以不用额外触发
  79. Else
  80. FirstChecked = True
  81. End If
  82. End If
  83. Next
  84. End If
  85. End Select
  86. '更改动画
  87. If Not IsChanged Then Return
  88. RefreshColor(Nothing, anime)
  89. '触发事件
  90. If Checked Then RaiseEvent Check(Me, raiseByMouse)
  91. RaiseCustomEvent()
  92. Catch ex As Exception
  93. Logger.Error(ex, "单选按钮勾选改变错误", LogBehavior.Toast)
  94. End Try
  95. End Sub
  96. Public ReadOnly Property Inlines As InlineCollection
  97. Get
  98. Return LabText.Inlines
  99. End Get
  100. End Property
  101. Public Property Text As String
  102. Get
  103. Return GetValue(TextProperty)
  104. End Get
  105. Set(value As String)
  106. SetValue(TextProperty, value)
  107. End Set
  108. End Property '内容
  109. Public Shared ReadOnly TextProperty As DependencyProperty = DependencyProperty.Register("Text", GetType(String), GetType(MyRadioButton), New PropertyMetadata(New PropertyChangedCallback(
  110. Sub(sender, e) If sender IsNot Nothing Then CType(sender, MyRadioButton).LabText.Text = e.NewValue)))
  111. Public Enum ColorState
  112. White
  113. Highlight
  114. End Enum
  115. Private _ColorType As ColorState = ColorState.White
  116. Public Property ColorType As ColorState
  117. Get
  118. Return _ColorType
  119. End Get
  120. Set(value As ColorState)
  121. _ColorType = value
  122. RefreshColor()
  123. End Set
  124. End Property '颜色类别
  125. '点击事件
  126. Public Event PreviewClick(sender As Object, e As RouteEventArgs)
  127. Private IsMouseDown As Boolean = False
  128. Private Sub Radiobox_MouseUp() Handles Me.MouseLeftButtonUp
  129. If Checked Then Return
  130. If Not IsMouseDown Then Return
  131. Logger.Info($"按下单选按钮:{Text}")
  132. IsMouseDown = False
  133. Dim e As New RouteEventArgs(True)
  134. RaiseEvent PreviewClick(Me, e)
  135. If e.Handled Then Return
  136. SetChecked(True, True, True)
  137. End Sub
  138. Private Sub Radiobox_MouseDown() Handles Me.MouseLeftButtonDown
  139. If Checked Then Return
  140. IsMouseDown = True
  141. RefreshColor()
  142. End Sub
  143. Private Sub Radiobox_MouseLeave() Handles Me.MouseLeave
  144. IsMouseDown = False
  145. End Sub
  146. '动画
  147. Private Const AnimationTimeOfMouseIn As Integer = 90 '鼠标指向动画长度
  148. Private Const AnimationTimeOfMouseOut As Integer = 150 '鼠标移出动画长度
  149. Private Const AnimationTimeOfCheck As Integer = 120 '勾选状态变更动画长度
  150. Private Sub RefreshColor(Optional obj = Nothing, Optional e = Nothing) Handles Me.MouseEnter, Me.MouseLeave, Me.Loaded
  151. Try
  152. If IsLoaded AndAlso AniControlEnabled = 0 AndAlso Not False.Equals(e) Then '防止默认属性变更触发动画,若强制不执行动画,则 e 为 False
  153. Select Case ColorType
  154. Case ColorState.White
  155. If Checked Then
  156. '勾选
  157. AniStart({
  158. AaColor(ShapeLogo, Shapes.Path.FillProperty, "ColorBrush3", AnimationTimeOfCheck),
  159. AaColor(LabText, TextBlock.ForegroundProperty, "ColorBrush3", AnimationTimeOfCheck)
  160. }, "MyRadioButton Checked " & Uuid)
  161. AniStart(AaColor(Me, BackgroundProperty, New MyColor(255, 255, 255) - Background, AnimationTimeOfCheck), "MyRadioButton Color " & Uuid)
  162. ElseIf IsMouseDown Then
  163. '按下
  164. AniStart(AaColor(Me, BackgroundProperty, New MyColor(120, Color8) - Background, 60), "MyRadioButton Color " & Uuid)
  165. ElseIf IsMouseOver Then
  166. '指向
  167. AniStart({
  168. AaColor(ShapeLogo, Shapes.Path.FillProperty, New MyColor(255, 255, 255) - ShapeLogo.Fill, AnimationTimeOfMouseIn),
  169. AaColor(LabText, TextBlock.ForegroundProperty, New MyColor(255, 255, 255) - LabText.Foreground, AnimationTimeOfMouseIn)
  170. }, "MyRadioButton Checked " & Uuid)
  171. AniStart(AaColor(Me, BackgroundProperty, New MyColor(50, Color8) - Background, AnimationTimeOfMouseIn), "MyRadioButton Color " & Uuid)
  172. Else
  173. '正常
  174. AniStart({
  175. AaColor(ShapeLogo, Shapes.Path.FillProperty, New MyColor(255, 255, 255) - ShapeLogo.Fill, AnimationTimeOfMouseOut),
  176. AaColor(LabText, TextBlock.ForegroundProperty, New MyColor(255, 255, 255) - LabText.Foreground, AnimationTimeOfMouseOut)
  177. }, "MyRadioButton Checked " & Uuid)
  178. AniStart(AaColor(Me, BackgroundProperty, ColorSemiTransparent - Background, AnimationTimeOfMouseOut), "MyRadioButton Color " & Uuid)
  179. End If
  180. Case ColorState.Highlight
  181. If Checked Then
  182. '勾选
  183. AniStart({
  184. AaColor(ShapeLogo, Shapes.Path.FillProperty, New MyColor(255, 255, 255) - ShapeLogo.Fill, AnimationTimeOfCheck),
  185. AaColor(LabText, TextBlock.ForegroundProperty, New MyColor(255, 255, 255) - LabText.Foreground, AnimationTimeOfCheck)
  186. }, "MyRadioButton Checked " & Uuid)
  187. AniStart(AaColor(Me, BackgroundProperty, "ColorBrush3", AnimationTimeOfCheck), "MyRadioButton Color " & Uuid)
  188. ElseIf IsMouseDown Then
  189. '按下
  190. AniStart(AaColor(Me, BackgroundProperty, "ColorBrush6", AnimationTimeOfMouseIn), "MyRadioButton Color " & Uuid)
  191. ElseIf IsMouseOver Then
  192. '指向
  193. AniStart({
  194. AaColor(ShapeLogo, Shapes.Path.FillProperty, "ColorBrush3", AnimationTimeOfMouseIn),
  195. AaColor(LabText, TextBlock.ForegroundProperty, "ColorBrush3", AnimationTimeOfMouseIn)
  196. }, "MyRadioButton Checked " & Uuid)
  197. AniStart(AaColor(Me, BackgroundProperty, "ColorBrush7", AnimationTimeOfMouseIn), "MyRadioButton Color " & Uuid)
  198. Else
  199. '正常
  200. AniStart({
  201. AaColor(ShapeLogo, Shapes.Path.FillProperty, "ColorBrush3", AnimationTimeOfMouseOut),
  202. AaColor(LabText, TextBlock.ForegroundProperty, "ColorBrush3", AnimationTimeOfMouseOut)
  203. }, "MyRadioButton Checked " & Uuid)
  204. AniStart(AaColor(Me, BackgroundProperty, ColorSemiTransparent - Background, AnimationTimeOfMouseOut), "MyRadioButton Color " & Uuid)
  205. End If
  206. End Select
  207. Else
  208. '不使用动画
  209. AniStop("MyRadioButton Checked " & Uuid)
  210. AniStop("MyRadioButton Color " & Uuid)
  211. Select Case ColorType
  212. Case ColorState.White
  213. If Checked Then
  214. Background = New MyColor(255, 255, 255)
  215. ShapeLogo.SetResourceReference(Shapes.Path.FillProperty, "ColorBrush3")
  216. LabText.SetResourceReference(TextBlock.ForegroundProperty, "ColorBrush3")
  217. Else
  218. Background = ColorSemiTransparent
  219. ShapeLogo.Fill = New MyColor(255, 255, 255)
  220. LabText.Foreground = New MyColor(255, 255, 255)
  221. End If
  222. Case ColorState.Highlight
  223. If Checked Then
  224. SetResourceReference(BackgroundProperty, "ColorBrush3")
  225. ShapeLogo.Fill = New MyColor(255, 255, 255)
  226. LabText.Foreground = New MyColor(255, 255, 255)
  227. Else
  228. Background = ColorSemiTransparent
  229. ShapeLogo.SetResourceReference(Shapes.Path.FillProperty, "ColorBrush3")
  230. LabText.SetResourceReference(TextBlock.ForegroundProperty, "ColorBrush3")
  231. End If
  232. End Select
  233. End If
  234. Catch ex As Exception
  235. Logger.Warn(ex, "刷新单选按钮颜色出错")
  236. End Try
  237. End Sub
  238. End Class