MyRadioButton.xaml.vb 12 KB

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