MyRadioButton.xaml.vb 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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, e) If sender IsNot Nothing Then CType(sender, MyRadioButton).LabText.Text = e.NewValue)))
  108. Public Enum ColorState
  109. White
  110. Highlight
  111. End Enum
  112. Private _ColorType As ColorState = ColorState.White
  113. Public Property ColorType As ColorState
  114. Get
  115. Return _ColorType
  116. End Get
  117. Set(value As ColorState)
  118. _ColorType = value
  119. RefreshColor()
  120. End Set
  121. End Property '颜色类别
  122. '点击事件
  123. Public Event PreviewClick(sender As Object, e As RouteEventArgs)
  124. Private IsMouseDown As Boolean = False
  125. Private Sub Radiobox_MouseUp() Handles Me.MouseLeftButtonUp
  126. If Checked Then Exit Sub
  127. If Not IsMouseDown Then Exit Sub
  128. Log("[Control] 按下单选按钮:" & Text)
  129. IsMouseDown = False
  130. Dim e As New RouteEventArgs(True)
  131. RaiseEvent PreviewClick(Me, e)
  132. If e.Handled Then Exit Sub
  133. SetChecked(True, True, True)
  134. End Sub
  135. Private Sub Radiobox_MouseDown() Handles Me.MouseLeftButtonDown
  136. If Checked Then Exit Sub
  137. IsMouseDown = True
  138. RefreshColor()
  139. End Sub
  140. Private Sub Radiobox_MouseLeave() Handles Me.MouseLeave
  141. IsMouseDown = False
  142. End Sub
  143. '动画
  144. Private Const AnimationTimeOfMouseIn As Integer = 90 '鼠标指向动画长度
  145. Private Const AnimationTimeOfMouseOut As Integer = 150 '鼠标移出动画长度
  146. Private Const AnimationTimeOfCheck As Integer = 120 '勾选状态变更动画长度
  147. Private Sub RefreshColor(Optional obj = Nothing, Optional e = Nothing) Handles Me.MouseEnter, Me.MouseLeave, Me.Loaded
  148. Try
  149. If IsLoaded AndAlso AniControlEnabled = 0 AndAlso Not False.Equals(e) Then '防止默认属性变更触发动画,若强制不执行动画,则 e 为 False
  150. Select Case ColorType
  151. Case ColorState.White
  152. If Checked Then
  153. '勾选
  154. AniStart({
  155. AaColor(ShapeLogo, Shapes.Path.FillProperty, "ColorBrush3", AnimationTimeOfCheck),
  156. AaColor(LabText, TextBlock.ForegroundProperty, "ColorBrush3", AnimationTimeOfCheck)
  157. }, "MyRadioButton Checked " & Uuid)
  158. AniStart(AaColor(Me, BackgroundProperty, New MyColor(255, 255, 255) - Background, AnimationTimeOfCheck), "MyRadioButton Color " & Uuid)
  159. ElseIf IsMouseDown Then
  160. '按下
  161. AniStart(AaColor(Me, BackgroundProperty, New MyColor(120, Color8) - Background, 60), "MyRadioButton Color " & Uuid)
  162. ElseIf IsMouseOver Then
  163. '指向
  164. AniStart({
  165. AaColor(ShapeLogo, Shapes.Path.FillProperty, New MyColor(255, 255, 255) - ShapeLogo.Fill, AnimationTimeOfMouseIn),
  166. AaColor(LabText, TextBlock.ForegroundProperty, New MyColor(255, 255, 255) - LabText.Foreground, AnimationTimeOfMouseIn)
  167. }, "MyRadioButton Checked " & Uuid)
  168. AniStart(AaColor(Me, BackgroundProperty, New MyColor(50, Color8) - Background, AnimationTimeOfMouseIn), "MyRadioButton Color " & Uuid)
  169. Else
  170. '正常
  171. AniStart({
  172. AaColor(ShapeLogo, Shapes.Path.FillProperty, New MyColor(255, 255, 255) - ShapeLogo.Fill, AnimationTimeOfMouseOut),
  173. AaColor(LabText, TextBlock.ForegroundProperty, New MyColor(255, 255, 255) - LabText.Foreground, AnimationTimeOfMouseOut)
  174. }, "MyRadioButton Checked " & Uuid)
  175. AniStart(AaColor(Me, BackgroundProperty, ColorSemiTransparent - Background, AnimationTimeOfMouseOut), "MyRadioButton Color " & Uuid)
  176. End If
  177. Case ColorState.Highlight
  178. If Checked Then
  179. '勾选
  180. AniStart({
  181. AaColor(ShapeLogo, Shapes.Path.FillProperty, New MyColor(255, 255, 255) - ShapeLogo.Fill, AnimationTimeOfCheck),
  182. AaColor(LabText, TextBlock.ForegroundProperty, New MyColor(255, 255, 255) - LabText.Foreground, AnimationTimeOfCheck)
  183. }, "MyRadioButton Checked " & Uuid)
  184. AniStart(AaColor(Me, BackgroundProperty, "ColorBrush3", AnimationTimeOfCheck), "MyRadioButton Color " & Uuid)
  185. ElseIf IsMouseDown Then
  186. '按下
  187. AniStart(AaColor(Me, BackgroundProperty, "ColorBrush6", AnimationTimeOfMouseIn), "MyRadioButton Color " & Uuid)
  188. ElseIf IsMouseOver Then
  189. '指向
  190. AniStart({
  191. AaColor(ShapeLogo, Shapes.Path.FillProperty, "ColorBrush3", AnimationTimeOfMouseIn),
  192. AaColor(LabText, TextBlock.ForegroundProperty, "ColorBrush3", AnimationTimeOfMouseIn)
  193. }, "MyRadioButton Checked " & Uuid)
  194. AniStart(AaColor(Me, BackgroundProperty, "ColorBrush7", AnimationTimeOfMouseIn), "MyRadioButton Color " & Uuid)
  195. Else
  196. '正常
  197. AniStart({
  198. AaColor(ShapeLogo, Shapes.Path.FillProperty, "ColorBrush3", AnimationTimeOfMouseOut),
  199. AaColor(LabText, TextBlock.ForegroundProperty, "ColorBrush3", AnimationTimeOfMouseOut)
  200. }, "MyRadioButton Checked " & Uuid)
  201. AniStart(AaColor(Me, BackgroundProperty, ColorSemiTransparent - Background, AnimationTimeOfMouseOut), "MyRadioButton Color " & Uuid)
  202. End If
  203. End Select
  204. Else
  205. '不使用动画
  206. AniStop("MyRadioButton Checked " & Uuid)
  207. AniStop("MyRadioButton Color " & Uuid)
  208. Select Case ColorType
  209. Case ColorState.White
  210. If Checked Then
  211. Background = New MyColor(255, 255, 255)
  212. ShapeLogo.SetResourceReference(Shapes.Path.FillProperty, "ColorBrush3")
  213. LabText.SetResourceReference(TextBlock.ForegroundProperty, "ColorBrush3")
  214. Else
  215. Background = ColorSemiTransparent
  216. ShapeLogo.Fill = New MyColor(255, 255, 255)
  217. LabText.Foreground = New MyColor(255, 255, 255)
  218. End If
  219. Case ColorState.Highlight
  220. If Checked Then
  221. SetResourceReference(BackgroundProperty, "ColorBrush3")
  222. ShapeLogo.Fill = New MyColor(255, 255, 255)
  223. LabText.Foreground = New MyColor(255, 255, 255)
  224. Else
  225. Background = ColorSemiTransparent
  226. ShapeLogo.SetResourceReference(Shapes.Path.FillProperty, "ColorBrush3")
  227. LabText.SetResourceReference(TextBlock.ForegroundProperty, "ColorBrush3")
  228. End If
  229. End Select
  230. End If
  231. Catch ex As Exception
  232. Log(ex, "刷新单选按钮颜色出错")
  233. End Try
  234. End Sub
  235. End Class