MyImage.vb 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. Public Class MyImage
  2. Inherits Image
  3. #Region "辅助属性注册"
  4. ''' <summary>
  5. ''' 网络图片的缓存有效期。
  6. ''' 在这个时间后,才会重新尝试下载图片。
  7. ''' </summary>
  8. Public FileCacheExpiredTime As New TimeSpan(7, 0, 0, 0) '7 天
  9. ''' <summary>
  10. ''' 是否允许将网络图片存储到本地用作缓存。
  11. ''' </summary>
  12. Public Property EnableCache As Boolean
  13. Get
  14. Return _EnableCache
  15. End Get
  16. Set(value As Boolean)
  17. _EnableCache = value
  18. End Set
  19. End Property
  20. Private _EnableCache As Boolean = True
  21. '将 Source 属性映射到 XAML
  22. Public Shared Shadows ReadOnly SourceProperty As DependencyProperty = DependencyProperty.Register(
  23. "Source", GetType(String), GetType(MyImage), New PropertyMetadata(New PropertyChangedCallback(
  24. Sub(sender, e) If sender IsNot Nothing Then CType(sender, MyImage).Source = e.NewValue.ToString())))
  25. #End Region
  26. Private _Source As String = ""
  27. ''' <summary>
  28. ''' 与 Image 的 Source 类似。
  29. ''' 若输入以 http 开头的字符串,则会尝试下载图片然后显示,图片会保存为本地缓存。
  30. ''' 支持 WebP 格式的图片。
  31. ''' </summary>
  32. Public Shadows Property Source As String '覆写 Image 的 Source 属性
  33. Get
  34. Return _Source
  35. End Get
  36. Set(value As String)
  37. If value = "" Then value = Nothing
  38. If _Source = value Then Exit Property
  39. _Source = value
  40. Dim TempPath As String = $"{PathTemp}MyImage\{GetHash(value)}.png"
  41. Try
  42. '空
  43. If value Is Nothing Then
  44. MyBase.Source = Nothing
  45. Exit Property
  46. End If
  47. '本地图片
  48. If Not value.StartsWithF("http") Then
  49. MyBase.Source = New MyBitmap(value)
  50. Exit Property
  51. End If
  52. '从缓存加载网络图片
  53. If EnableCache AndAlso File.Exists(TempPath) Then
  54. MyBase.Source = New MyBitmap(TempPath)
  55. If (Date.Now - File.GetCreationTime(TempPath)) < FileCacheExpiredTime Then
  56. Exit Property '无需刷新缓存
  57. Else
  58. File.Delete(TempPath) '需要刷新缓存
  59. End If
  60. Else
  61. MyBase.Source = Nothing '清空显示
  62. End If
  63. '下载网络图片
  64. RunInNewThread(
  65. Sub()
  66. Dim Url As String = value '重新捕获变量,以检测在下载过程中 Source 被修改的情况
  67. Dim Retried As Boolean = False
  68. RetryStart:
  69. Dim TempDownloadingPath As String = TempPath & RandomInteger(0, 10000000)
  70. Try
  71. Log("[MyImage] 正在下载图片:" & Url)
  72. NetDownload(Url, TempDownloadingPath, True)
  73. If Url <> Source Then
  74. '若 Source 在下载时被修改,则不显示
  75. File.Delete(TempDownloadingPath)
  76. ElseIf EnableCache Then
  77. '保存缓存并显示
  78. Rename(TempDownloadingPath, TempPath)
  79. RunInUi(Sub() MyBase.Source = New MyBitmap(TempPath))
  80. Else
  81. '直接显示
  82. RunInUiWait(Sub() MyBase.Source = New MyBitmap(TempDownloadingPath))
  83. File.Delete(TempDownloadingPath)
  84. End If
  85. Catch ex As Exception
  86. Try
  87. File.Delete(TempDownloadingPath)
  88. Catch
  89. End Try
  90. If Not Retried Then
  91. Log(ex, $"下载图片可重试地失败({Url})", LogLevel.Developer)
  92. Retried = True
  93. Thread.Sleep(1000)
  94. GoTo RetryStart
  95. Else
  96. Log(ex, $"下载图片失败({Url})", LogLevel.Hint)
  97. End If
  98. End Try
  99. End Sub, "MyImage PicLoader " & GetUuid() & "#", ThreadPriority.BelowNormal)
  100. Catch ex As Exception
  101. Log(ex, $"加载图片失败({value})", LogLevel.Hint)
  102. Try
  103. File.Delete(TempPath) '删除缓存,以免缓存出现问题导致一直加载失败
  104. Catch
  105. End Try
  106. End Try
  107. End Set
  108. End Property
  109. End Class