MyRadioButton.xaml.vb 13 KB

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