MyListItem.xaml.vb 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. Public Class MyListItem
  2. Implements IMyRadio
  3. Public Event Click(sender As Object, e As MouseButtonEventArgs)
  4. Public Event LogoClick(sender As Object, e As MouseButtonEventArgs)
  5. Public Event Check(sender As Object, e As RouteEventArgs) Implements IMyRadio.Check
  6. Public Event Changed(sender As Object, e As RouteEventArgs) Implements IMyRadio.Changed
  7. #Region "后加载控件"
  8. '指向背景
  9. Private _RectBack As Border = Nothing
  10. Public ReadOnly Property RectBack As Border
  11. Get
  12. If _RectBack Is Nothing Then
  13. Dim Rect As New Border With {
  14. .Name = "RectBack",
  15. .CornerRadius = New CornerRadius(If(IsScaleAnimationEnabled, 6, 0)),
  16. .RenderTransform = If(IsScaleAnimationEnabled, New ScaleTransform(0.8, 0.8), Nothing),
  17. .RenderTransformOrigin = New Point(0.5, 0.5),
  18. .BorderThickness = New Thickness(GetWPFSize(1)),
  19. .SnapsToDevicePixels = True,
  20. .IsHitTestVisible = False,
  21. .Opacity = 0
  22. }
  23. Rect.SetResourceReference(Border.BackgroundProperty, "ColorBrush7")
  24. Rect.SetResourceReference(Border.BorderBrushProperty, "ColorBrush6")
  25. SetColumnSpan(Rect, 999)
  26. SetRowSpan(Rect, 999)
  27. Children.Insert(0, Rect)
  28. _RectBack = Rect
  29. '<!--<Border x:Name = "RectBack" CornerRadius="3" RenderTransformOrigin="0.5,0.5" SnapsToDevicePixels="True"
  30. 'IsHitTestVisible = "False" Opacity="0" BorderThickness="1"
  31. 'Grid.ColumnSpan = "4" Background="{DynamicResource ColorBrush7}" BorderBrush="{DynamicResource ColorBrush6}"/>-->
  32. End If
  33. Return _RectBack
  34. End Get
  35. End Property
  36. '按钮
  37. Public ButtonStack As FrameworkElement
  38. '图标
  39. Public PathLogo As FrameworkElement
  40. '勾选条
  41. Public RectCheck As Border
  42. '副文本
  43. Private _LabInfo As TextBlock = Nothing
  44. Public ReadOnly Property LabInfo As TextBlock
  45. Get
  46. If _LabInfo Is Nothing Then
  47. Dim Lab As New TextBlock With {
  48. .Name = "LabInfo",
  49. .SnapsToDevicePixels = False,
  50. .UseLayoutRounding = False,
  51. .HorizontalAlignment = HorizontalAlignment.Left,
  52. .IsHitTestVisible = False,
  53. .TextTrimming = TextTrimming.CharacterEllipsis,
  54. .Visibility = Visibility.Collapsed,
  55. .FontSize = 12,
  56. .Margin = New Thickness(4, 0, 0, 0),
  57. .Opacity = 0.6
  58. }
  59. SetColumn(Lab, 3)
  60. SetRow(Lab, 2)
  61. Children.Add(Lab)
  62. _LabInfo = Lab
  63. '<TextBlock Grid.Row="2" SnapsToDevicePixels="False" UseLayoutRounding="False" HorizontalAlignment="Left" x:Name = "LabInfo" IsHitTestVisible="False" Grid.Column="2"
  64. 'TextTrimming = "CharacterEllipsis" Visibility="Collapsed" FontSize="12" Foreground="{StaticResource ColorBrushGray2}" Margin="4,0,0,0" />
  65. End If
  66. Return _LabInfo
  67. End Get
  68. End Property
  69. #End Region
  70. #Region "自定义属性"
  71. 'Uuid
  72. Public Uuid As Integer = GetUuid()
  73. ''' <summary>
  74. ''' 是否启用缩放动画。
  75. ''' </summary>
  76. Public Property IsScaleAnimationEnabled As Boolean
  77. Get
  78. Return _IsScaleAnimationEnabled
  79. End Get
  80. Set
  81. _IsScaleAnimationEnabled = Value
  82. If _RectBack IsNot Nothing Then RectBack.CornerRadius = New CornerRadius(If(Value, 6, 0))
  83. End Set
  84. End Property
  85. Private _IsScaleAnimationEnabled As Boolean = True
  86. '边距
  87. Public Property PaddingLeft As Integer
  88. Get
  89. Return ColumnPaddingLeft.Width.Value
  90. End Get
  91. Set(value As Integer)
  92. ColumnPaddingLeft.Width = New GridLength(value)
  93. End Set
  94. End Property
  95. Public Property PaddingRight As Integer
  96. Get
  97. Return ColumnPaddingRight.Width.Value
  98. End Get
  99. Set(value As Integer)
  100. ColumnPaddingRight.Width = New GridLength(value)
  101. End Set
  102. End Property
  103. '按钮
  104. Private _Buttons As IEnumerable
  105. Public Property Buttons As IEnumerable
  106. Get
  107. Return _Buttons
  108. End Get
  109. Set(value As IEnumerable)
  110. _Buttons = value
  111. '没有特殊按钮,移除原 Stack
  112. If Not IsNothing(ButtonStack) Then
  113. Children.Remove(ButtonStack)
  114. ButtonStack = Nothing
  115. End If
  116. '获取按钮数量
  117. Dim Count As Integer = 0
  118. For Each Counter In value
  119. Count += 1
  120. Next
  121. '添加新 Stack
  122. Select Case Count
  123. Case 0
  124. '没有按钮,不添加新的
  125. Case 1
  126. '只有一个按钮
  127. For Each Btn As MyIconButton In value
  128. If Btn.Height.Equals(Double.NaN) Then Btn.Height = 23
  129. If Btn.Width.Equals(Double.NaN) Then Btn.Width = 23
  130. With Btn
  131. .Opacity = 0
  132. .Margin = New Thickness(0, 0, 5, 0)
  133. .SnapsToDevicePixels = False
  134. .HorizontalAlignment = HorizontalAlignment.Right
  135. .VerticalAlignment = VerticalAlignment.Center
  136. .SnapsToDevicePixels = False
  137. .UseLayoutRounding = False
  138. End With
  139. SetColumn(Btn, 4)
  140. SetColumnSpan(Btn, 4)
  141. SetRowSpan(Btn, 4)
  142. Children.Add(Btn)
  143. ButtonStack = Btn
  144. Next
  145. Case Else
  146. '有复数按钮,使用 StackPanel
  147. ButtonStack = New StackPanel With {.Opacity = 0, .Margin = New Thickness(0, 0, 5, 0), .SnapsToDevicePixels = False, .Orientation = Orientation.Horizontal, .HorizontalAlignment = HorizontalAlignment.Right, .VerticalAlignment = VerticalAlignment.Center, .UseLayoutRounding = False}
  148. SetColumn(ButtonStack, 4)
  149. SetColumnSpan(ButtonStack, 4)
  150. SetRowSpan(ButtonStack, 4)
  151. '构造按钮
  152. For Each Btn As MyIconButton In value
  153. If Btn.Height.Equals(Double.NaN) Then Btn.Height = 23
  154. If Btn.Width.Equals(Double.NaN) Then Btn.Width = 23
  155. CType(ButtonStack, StackPanel).Children.Add(Btn)
  156. Next
  157. Children.Add(ButtonStack)
  158. End Select
  159. End Set
  160. End Property
  161. '标题
  162. Public Property Title As String
  163. Get
  164. Return GetValue(TitleProperty)
  165. End Get
  166. Set(value As String)
  167. SetValue(TitleProperty, value)
  168. End Set
  169. End Property
  170. Public Shared ReadOnly TitleProperty As DependencyProperty = DependencyProperty.Register("Title", GetType(String), GetType(MyListItem))
  171. '字号
  172. Public Property FontSize As Double
  173. Get
  174. Return GetValue(FontSizeProperty)
  175. End Get
  176. Set(value As Double)
  177. SetValue(FontSizeProperty, value)
  178. End Set
  179. End Property
  180. Public Shared ReadOnly FontSizeProperty As DependencyProperty = DependencyProperty.Register("FontSize", GetType(Double), GetType(MyListItem), New PropertyMetadata(CType(14, Double)))
  181. '信息
  182. Private _Info As String = ""
  183. Public Property Info As String
  184. Get
  185. Return _Info
  186. End Get
  187. Set(value As String)
  188. If _Info = value Then Exit Property
  189. value = value.Replace(vbCr, "").Replace(vbLf, "")
  190. _Info = value
  191. LabInfo.Text = value
  192. LabInfo.Visibility = If(value = "", Visibility.Collapsed, Visibility.Visible)
  193. End Set
  194. End Property
  195. '图片
  196. Private _Logo As String = ""
  197. Public Property Logo As String
  198. Get
  199. Return _Logo
  200. End Get
  201. Set(value As String)
  202. If _Logo = value Then Exit Property
  203. _Logo = value
  204. '删除旧 Logo
  205. If Not IsNothing(PathLogo) Then Children.Remove(PathLogo)
  206. '添加新 Logo
  207. If Not _Logo = "" Then
  208. If _Logo.ToLower.StartsWith("http") Then
  209. '网络图片
  210. PathLogo = New Image With {
  211. .IsHitTestVisible = LogoClickable,
  212. .Source = New ImageSourceConverter().ConvertFromString(_Logo),
  213. .RenderTransformOrigin = New Point(0.5, 0.5),
  214. .RenderTransform = New ScaleTransform With {.ScaleX = LogoScale, .ScaleY = LogoScale},
  215. .SnapsToDevicePixels = True, .UseLayoutRounding = False}
  216. RenderOptions.SetBitmapScalingMode(PathLogo, BitmapScalingMode.Linear)
  217. ElseIf _Logo.ToLower.EndsWith(".png") Then
  218. '位图
  219. Dim Bitmap = New MyBitmap(_Logo)
  220. PathLogo = New Canvas With {
  221. .IsHitTestVisible = LogoClickable,
  222. .Background = Bitmap,
  223. .RenderTransformOrigin = New Point(0.5, 0.5),
  224. .RenderTransform = New ScaleTransform With {.ScaleX = LogoScale, .ScaleY = LogoScale},
  225. .SnapsToDevicePixels = True, .UseLayoutRounding = False}
  226. 'If Bitmap.Pic.Width = 16 AndAlso Bitmap.Pic.Height = 16 Then
  227. ' '使用最适合 16x16 物品图片显示的大小
  228. ' RenderOptions.SetBitmapScalingMode(PathLogo, BitmapScalingMode.NearestNeighbor)
  229. ' PathLogo.HorizontalAlignment = HorizontalAlignment.Center : PathLogo.VerticalAlignment = VerticalAlignment.Center
  230. ' PathLogo.Width = GetWPFSize(Math.Floor(GetPixelSize(32) / 16) * 16) : PathLogo.Height = PathLogo.Width
  231. 'Else
  232. PathLogo.HorizontalAlignment = HorizontalAlignment.Stretch : PathLogo.VerticalAlignment = VerticalAlignment.Stretch
  233. RenderOptions.SetBitmapScalingMode(PathLogo, BitmapScalingMode.HighQuality)
  234. 'End If
  235. Else
  236. '矢量图
  237. PathLogo = New Shapes.Path With {
  238. .IsHitTestVisible = LogoClickable, .HorizontalAlignment = HorizontalAlignment.Center, .VerticalAlignment = VerticalAlignment.Center, .Stretch = Stretch.Uniform,
  239. .Data = (New GeometryConverter).ConvertFromString(_Logo),
  240. .RenderTransformOrigin = New Point(0.5, 0.5),
  241. .RenderTransform = New ScaleTransform With {.ScaleX = LogoScale, .ScaleY = LogoScale},
  242. .SnapsToDevicePixels = False, .UseLayoutRounding = False}
  243. PathLogo.SetBinding(Shapes.Path.FillProperty, New Binding("Foreground") With {.Source = Me})
  244. End If
  245. SetColumn(PathLogo, 2)
  246. SetRowSpan(PathLogo, 4)
  247. OnSizeChanged() '设置边距
  248. Children.Add(PathLogo)
  249. '图标的点击事件
  250. If LogoClickable Then
  251. AddHandler PathLogo.MouseLeave, Sub(sender, e) IsLogoDown = False
  252. AddHandler PathLogo.MouseLeftButtonDown, Sub(sender, e) IsLogoDown = True
  253. AddHandler PathLogo.MouseLeftButtonUp, Sub(sender, e) If IsLogoDown Then IsLogoDown = False : RaiseEvent LogoClick(sender, e)
  254. End If
  255. End If
  256. '改变行距
  257. ColumnLogo.Width = New GridLength(If(_Logo = "", 0, 34) + If(Height < 40, 0, 4))
  258. End Set
  259. End Property
  260. Private _LogoScale As Double = 1
  261. Public Property LogoScale() As Double
  262. Get
  263. Return _LogoScale
  264. End Get
  265. Set(value As Double)
  266. _LogoScale = value
  267. If Not IsNothing(PathLogo) Then PathLogo.RenderTransform = New ScaleTransform With {.ScaleX = LogoScale, .ScaleY = LogoScale}
  268. End Set
  269. End Property
  270. '图标的点击
  271. Public Property LogoClickable As Boolean = False
  272. Private IsLogoDown As Boolean = False
  273. '勾选选项
  274. Public Enum CheckType
  275. None
  276. Clickable
  277. RadioBox
  278. CheckBox
  279. End Enum
  280. Private _Type As CheckType = CheckType.None
  281. Public Property Type As CheckType
  282. Get
  283. Return _Type
  284. End Get
  285. Set(value As CheckType)
  286. If _Type = value Then Exit Property
  287. _Type = value
  288. '切换左栏大小
  289. ColumnCheck.Width = New GridLength(If(_Type = CheckType.None OrElse _Type = CheckType.Clickable, If(Height < 40, 4, 2), 6))
  290. '切换竖条控件
  291. If _Type = CheckType.None OrElse _Type = CheckType.Clickable Then
  292. '移除竖条控件
  293. If Not IsNothing(RectCheck) Then
  294. Children.Remove(RectCheck)
  295. RectCheck = Nothing
  296. End If
  297. SetChecked(False, False, False)
  298. Else
  299. '添加竖条控件
  300. If IsNothing(RectCheck) Then
  301. RectCheck = New Border With {.Width = 5, .Height = If(Checked, Double.NaN, 0), .CornerRadius = New CornerRadius(2, 2, 2, 2),
  302. .VerticalAlignment = If(Checked, VerticalAlignment.Stretch, VerticalAlignment.Center), .HorizontalAlignment = HorizontalAlignment.Left, .UseLayoutRounding = False, .SnapsToDevicePixels = False,
  303. .Margin = If(Checked, New Thickness(-1, 6, 0, 6), New Thickness(-1, 0, 0, 0))}
  304. RectCheck.SetResourceReference(Border.BackgroundProperty, "ColorBrush3")
  305. SetRowSpan(RectCheck, 4)
  306. Children.Add(RectCheck)
  307. End If
  308. End If
  309. End Set
  310. End Property
  311. '适应尺寸
  312. Private Sub OnSizeChanged() Handles Me.SizeChanged
  313. ColumnCheck.Width = New GridLength(If(_Type = CheckType.None OrElse _Type = CheckType.Clickable, If(Height < 40, 4, 2), 6))
  314. ColumnLogo.Width = New GridLength(If(_Logo = "", 0, 34) + If(Height < 40, 0, 4))
  315. If Not IsNothing(PathLogo) Then
  316. If _Logo.EndsWith(".png") Then
  317. PathLogo.Margin = New Thickness(4, 5, 3, 5)
  318. Else
  319. PathLogo.Margin = New Thickness(If(Height < 40, 6, 8), 8, If(Height < 40, 4, 6), 8)
  320. End If
  321. End If
  322. LabTitle.Margin = New Thickness(4, 0, 0, If(Height < 40, 0, 2))
  323. End Sub
  324. '勾选状态
  325. Private _Checked As Boolean = False
  326. Public Property Checked As Boolean
  327. Get
  328. Return _Checked
  329. End Get
  330. Set(value As Boolean)
  331. SetChecked(value, False, True)
  332. End Set
  333. End Property
  334. ''' <summary>
  335. ''' 手动设置 Checked 属性。
  336. ''' </summary>
  337. ''' <param name="value">新的 Checked 属性。</param>
  338. ''' <param name="user">是否由用户引发。</param>
  339. ''' <param name="anime">是否执行动画。</param>
  340. Public Sub SetChecked(value As Boolean, user As Boolean, anime As Boolean)
  341. Try
  342. '自定义属性基础
  343. Dim ChangedEventArgs As New RouteEventArgs(user)
  344. Dim RawValue = _Checked
  345. If Type = CheckType.RadioBox Then
  346. If IsInitialized AndAlso Not value = _Checked Then
  347. _Checked = value
  348. RaiseEvent Changed(Me, ChangedEventArgs)
  349. If ChangedEventArgs.Handled Then
  350. _Checked = RawValue
  351. Exit Sub
  352. End If
  353. End If
  354. _Checked = value
  355. Else
  356. If value = _Checked Then Exit Sub
  357. _Checked = value
  358. If IsInitialized Then
  359. RaiseEvent Changed(Me, ChangedEventArgs)
  360. If ChangedEventArgs.Handled Then
  361. _Checked = RawValue
  362. Exit Sub
  363. End If
  364. End If
  365. End If
  366. If value Then
  367. Dim CheckEventArgs As New RouteEventArgs(user)
  368. RaiseEvent Check(Me, CheckEventArgs)
  369. If CheckEventArgs.Handled Then Exit Sub
  370. End If
  371. '保证只有一个单选 ListItem 选中
  372. If Type = CheckType.RadioBox Then
  373. If IsNothing(Parent) Then Exit Sub
  374. Dim RadioboxList As New List(Of MyListItem)
  375. Dim CheckedCount As Integer = 0
  376. '收集控件列表与选中个数
  377. For Each Control In CType(Parent, Object).Children
  378. If TypeOf Control Is MyListItem AndAlso CType(Control, MyListItem).Type = CheckType.RadioBox Then
  379. RadioboxList.Add(Control)
  380. If Control.Checked Then CheckedCount += 1
  381. End If
  382. Next
  383. '判断选中情况
  384. Select Case CheckedCount
  385. Case 0
  386. '没有任何单选框被选中,选择第一个
  387. RadioboxList(0).Checked = True
  388. Case Is > 1
  389. '选中项目多于 1 个
  390. If Me.Checked Then
  391. '如果本控件选中,则取消其他所有控件的选中
  392. For Each Control As MyListItem In RadioboxList
  393. If Control.Checked AndAlso Not Control.Equals(Me) Then Control.Checked = False
  394. Next
  395. Else
  396. '如果本控件未选中,则只保留第一个选中的控件
  397. Dim FirstChecked = False
  398. For Each Control As MyListItem In RadioboxList
  399. If Control.Checked Then
  400. If FirstChecked Then
  401. Control.Checked = False '修改 Checked 会自动触发 Change 事件,所以不用额外触发
  402. Else
  403. FirstChecked = True
  404. End If
  405. End If
  406. Next
  407. End If
  408. End Select
  409. End If
  410. '更改动画
  411. If IsLoaded AndAlso AniControlEnabled = 0 AndAlso anime Then '防止默认属性变更触发动画
  412. Dim Anim As New List(Of AniData)
  413. If Checked Then
  414. '由无变有
  415. If Not IsNothing(RectCheck) Then
  416. Dim Delta = ActualHeight - RectCheck.ActualHeight - 12
  417. Anim.Add(AaHeight(RectCheck, Delta * 0.4, 200,, New AniEaseOutFluent(AniEasePower.Weak)))
  418. Anim.Add(AaHeight(RectCheck, Delta * 0.6, 300,, New AniEaseOutBack(AniEasePower.Weak)))
  419. Anim.Add(AaOpacity(RectCheck, 1 - RectCheck.Opacity, 30))
  420. RectCheck.VerticalAlignment = VerticalAlignment.Center
  421. RectCheck.Margin = New Thickness(-1, 0, 0, 0)
  422. End If
  423. Anim.Add(AaColor(Me, ForegroundProperty, "ColorBrush3", 200))
  424. Else
  425. '由有变无
  426. If Not IsNothing(RectCheck) Then
  427. 'Anim.Add(AaWidth(RectCheck, -RectCheck.Width, 120,, New AniEaseInFluent))
  428. Anim.Add(AaHeight(RectCheck, -RectCheck.ActualHeight, 120,, New AniEaseInFluent(AniEasePower.Weak)))
  429. Anim.Add(AaOpacity(RectCheck, -RectCheck.Opacity, 70, 40))
  430. RectCheck.VerticalAlignment = VerticalAlignment.Center
  431. End If
  432. Anim.Add(AaColor(Me, ForegroundProperty, "ColorBrush1", 120))
  433. End If
  434. AniStart(Anim, "MyListItem Checked " & Uuid)
  435. Else
  436. '不使用动画
  437. If Checked Then
  438. 'If Not IsNothing(RectCheck) Then RectCheck.Width = 4
  439. If Not IsNothing(RectCheck) Then
  440. RectCheck.Height = Double.NaN
  441. RectCheck.Margin = New Thickness(-1, 6, 0, 6)
  442. RectCheck.Opacity = 1
  443. RectCheck.VerticalAlignment = VerticalAlignment.Stretch
  444. End If
  445. SetResourceReference(ForegroundProperty, "ColorBrush3")
  446. Else
  447. 'If Not IsNothing(RectCheck) Then RectCheck.Width = 0
  448. If Not IsNothing(RectCheck) Then
  449. RectCheck.Height = 0
  450. RectCheck.Margin = New Thickness(-1, 0, 0, 0)
  451. RectCheck.Opacity = 0
  452. RectCheck.VerticalAlignment = VerticalAlignment.Center
  453. End If
  454. SetResourceReference(ForegroundProperty, "ColorBrush1")
  455. End If
  456. End If
  457. Catch ex As Exception
  458. Log(ex, "设置 Checked 失败")
  459. End Try
  460. End Sub
  461. '前景色绑定
  462. Public Property Foreground As Brush
  463. Get
  464. Return GetValue(ForegroundProperty)
  465. End Get
  466. Set(value As Brush)
  467. SetValue(ForegroundProperty, value)
  468. End Set
  469. End Property
  470. Public Shared ReadOnly ForegroundProperty As DependencyProperty = DependencyProperty.Register("Foreground", GetType(Brush), GetType(MyListItem), New PropertyMetadata(CType(Color1, SolidColorBrush)))
  471. '菜单与按钮绑定
  472. Public ContentHandler As Action(Of MyListItem, EventArgs)
  473. #End Region
  474. #Region "点击"
  475. '触发点击事件
  476. Private Sub Button_MouseUp(sender As Object, e As MouseButtonEventArgs) Handles Me.PreviewMouseLeftButtonUp
  477. If IsMouseDown Then
  478. RaiseEvent Click(sender, e)
  479. If e.Handled Then Exit Sub
  480. '触发自定义事件
  481. If Not String.IsNullOrEmpty(EventType) Then
  482. ModEvent.TryStartEvent(EventType, EventData)
  483. e.Handled = True
  484. End If
  485. If e.Handled Then Exit Sub
  486. '实际的单击处理
  487. Select Case Type
  488. Case CheckType.Clickable
  489. Log("[Control] 按下单击列表项:" & Title)
  490. Case CheckType.RadioBox
  491. Log("[Control] 按下单选列表项:" & Title)
  492. If Not Checked Then SetChecked(True, True, True)
  493. Case CheckType.CheckBox
  494. Log("[Control] 按下复选列表项(" & (Not Checked).ToString & "):" & Title)
  495. SetChecked(Not Checked, True, True)
  496. End Select
  497. End If
  498. 'AniStart({
  499. ' AaScaleTransform(Me, 1.004 - CType(RenderTransform, ScaleTransform).ScaleX, 150,, New AniEaseOutFluent),
  500. ' AaScaleTransform(Me, -0.004, 100, 150, New AniEaseInFluent)
  501. ' }, "MyListItem Scale " & Uuid)
  502. End Sub
  503. '鼠标点击判定
  504. Private IsMouseDown As Boolean = False
  505. Private Sub Button_MouseDown(sender As Object, e As MouseButtonEventArgs) Handles Me.PreviewMouseLeftButtonDown
  506. If IsMouseDirectlyOver AndAlso Not Type = CheckType.None Then
  507. IsMouseDown = True
  508. If Not IsNothing(ButtonStack) Then ButtonStack.IsHitTestVisible = False
  509. End If
  510. 'AniStart({
  511. ' AaScaleTransform(Me, 0.985 - CType(RenderTransform, ScaleTransform).ScaleX, 50,, New AniEaseOutFluent)
  512. ' }, "MyListItem Scale " & Uuid)
  513. End Sub
  514. Private Sub Button_MouseLeave(sender As Object, e As Object) Handles Me.MouseLeave, Me.PreviewMouseLeftButtonUp
  515. IsMouseDown = False
  516. If Not IsNothing(ButtonStack) Then ButtonStack.IsHitTestVisible = True
  517. End Sub
  518. '实现自定义事件
  519. Public Property EventType As String
  520. Get
  521. Return GetValue(EventTypeProperty)
  522. End Get
  523. Set(value As String)
  524. SetValue(EventTypeProperty, value)
  525. End Set
  526. End Property
  527. Public Shared ReadOnly EventTypeProperty As DependencyProperty = DependencyProperty.Register("EventType", GetType(String), GetType(MyListItem), New PropertyMetadata(Nothing))
  528. Public Property EventData As String
  529. Get
  530. Return GetValue(EventDataProperty)
  531. End Get
  532. Set(value As String)
  533. SetValue(EventDataProperty, value)
  534. End Set
  535. End Property
  536. Public Shared ReadOnly EventDataProperty As DependencyProperty = DependencyProperty.Register("EventData", GetType(String), GetType(MyListItem), New PropertyMetadata(Nothing))
  537. #End Region
  538. Private StateLast As String
  539. Public IsMouseOverAnimationEnabled As Boolean = True
  540. Public Sub RefreshColor(sender As Object, e As EventArgs) Handles Me.MouseEnter, Me.MouseLeave, Me.MouseLeftButtonDown, Me.MouseLeftButtonUp
  541. '菜单虚拟化检测
  542. If ContentHandler IsNot Nothing Then
  543. ContentHandler(sender, e)
  544. ContentHandler = Nothing
  545. End If
  546. '判断当前颜色
  547. Dim StateNew As String, Time As Integer
  548. If IsMouseDown AndAlso Not (Type = CheckType.RadioBox AndAlso Checked) Then
  549. StateNew = "MouseDown"
  550. Time = 120
  551. Else
  552. If IsMouseOver AndAlso IsMouseOverAnimationEnabled Then
  553. StateNew = "MouseOver"
  554. Time = 120
  555. Else
  556. StateNew = "Idle"
  557. Time = 180
  558. End If
  559. End If
  560. If StateLast = StateNew Then Exit Sub
  561. StateLast = StateNew
  562. '触发颜色动画
  563. If IsLoaded AndAlso AniControlEnabled = 0 Then '防止默认属性变更触发动画
  564. '有动画
  565. Dim Ani As New List(Of AniData)
  566. If IsMouseOver AndAlso IsMouseOverAnimationEnabled Then
  567. If ButtonStack IsNot Nothing Then Ani.Add(AaOpacity(ButtonStack, 1 - ButtonStack.Opacity, Time * 0.7, Time * 0.3))
  568. Ani.AddRange({
  569. AaColor(RectBack, Border.BackgroundProperty, If(IsMouseDown, "ColorBrush6", "ColorBrush9"), Time),
  570. AaOpacity(RectBack, 1 - RectBack.Opacity, Time,, New AniEaseOutFluent)
  571. })
  572. If IsScaleAnimationEnabled Then
  573. Ani.Add(AaScaleTransform(RectBack, 1 - CType(RectBack.RenderTransform, ScaleTransform).ScaleX, Time * 1.6,, New AniEaseOutFluent))
  574. If IsMouseDown Then
  575. Ani.Add(AaScaleTransform(Me, 0.98 - CType(Me.RenderTransform, ScaleTransform).ScaleX, Time * 0.9,, New AniEaseOutFluent))
  576. Else
  577. Ani.Add(AaScaleTransform(Me, 1 - CType(Me.RenderTransform, ScaleTransform).ScaleX, Time * 1.2,, New AniEaseOutFluent))
  578. End If
  579. End If
  580. Else
  581. If ButtonStack IsNot Nothing Then Ani.Add(AaOpacity(ButtonStack, -ButtonStack.Opacity, Time * 0.5))
  582. Ani.Add(AaOpacity(RectBack, -RectBack.Opacity, Time))
  583. If IsScaleAnimationEnabled Then Ani.AddRange({
  584. AaColor(RectBack, Border.BackgroundProperty, If(IsMouseDown, "ColorBrush6", "ColorBrush7"), Time),
  585. AaScaleTransform(Me, 1 - CType(Me.RenderTransform, ScaleTransform).ScaleX, Time * 3,, New AniEaseOutFluent),
  586. AaScaleTransform(RectBack, 0.996 - CType(RectBack.RenderTransform, ScaleTransform).ScaleX, Time,, New AniEaseOutFluent),
  587. AaScaleTransform(RectBack, -0.246, 1,,, True)
  588. })
  589. End If
  590. AniStart(Ani, "ListItem Color " & Uuid)
  591. Else
  592. '无动画
  593. If IsMouseOver AndAlso IsMouseOverAnimationEnabled Then
  594. If ButtonStack IsNot Nothing Then ButtonStack.Opacity = 1
  595. '由于鼠标已经移入,所以直接实例化 RectBack
  596. RectBack.Background = Color9
  597. RectBack.Opacity = 1
  598. RectBack.RenderTransform = New ScaleTransform(1, 1)
  599. Me.RenderTransform = New ScaleTransform(1, 1)
  600. Else
  601. If ButtonStack IsNot Nothing Then ButtonStack.Opacity = 0
  602. Me.RenderTransform = New ScaleTransform(1, 1)
  603. If _RectBack IsNot Nothing Then
  604. If IsScaleAnimationEnabled Then RectBack.Background = Color7
  605. RectBack.Opacity = 0
  606. RectBack.RenderTransform = New ScaleTransform(0.75, 0.75)
  607. End If
  608. End If
  609. AniStop("ListItem Color " & Uuid)
  610. End If
  611. End Sub
  612. Private Sub MyListItem_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
  613. If Checked Then
  614. SetResourceReference(ForegroundProperty, "ColorBrush3")
  615. Else
  616. SetResourceReference(ForegroundProperty, "ColorBrush1")
  617. End If
  618. If EventType = "打开帮助" Then
  619. Try
  620. Dim NewElem = New HelpEntry(GetEventAbsoluteUrls(EventData, EventType)(0)).SetToListItem(Me)
  621. Catch ex As Exception
  622. Log(ex, "设置帮助 MyListItem 失败", LogLevel.Msgbox)
  623. End Try
  624. End If
  625. End Sub
  626. Public Overrides Function ToString() As String
  627. Return Title
  628. End Function
  629. End Class