LazyLoadBehavior.vb 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. Public Module LazyLoadBehavior
  2. ''' <summary>
  3. ''' 指定首次进入 ScrollViewer 的可视范围时执行的操作。
  4. ''' </summary>
  5. <Runtime.CompilerServices.Extension()>
  6. Public Sub OnFirstEnterScrollViewerViewport(obj As DependencyObject, value As Action)
  7. obj.SetValue(IsInViewportProperty, value)
  8. End Sub
  9. Private ReadOnly IsInViewportProperty As DependencyProperty =
  10. DependencyProperty.RegisterAttached("IsInViewport", GetType(Action), GetType(LazyLoadBehavior),
  11. New PropertyMetadata(Nothing, AddressOf OnIsInViewportChanged))
  12. Private Sub OnIsInViewportChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
  13. Dim Element = TryCast(d, FrameworkElement)
  14. If Element Is Nothing OrElse e.NewValue Is Nothing Then Return
  15. Dim Handled As Boolean = False
  16. Dim Handler As EventHandler =
  17. Sub()
  18. If Handled Then Return
  19. '判断元素是否可见
  20. If Element.RenderSize.Width < Double.Epsilon Then Return
  21. If Not Element.IsVisible Then Return
  22. '判断是否在 ScrollViewer 的可视区域内
  23. Dim Scroll = FindParentScrollViewer(Element)
  24. If Scroll Is Nothing Then Return
  25. If Not New Rect(0, 0, Scroll.ViewportWidth, Scroll.ViewportHeight).IntersectsWith(
  26. Element.TransformToAncestor(Scroll).TransformBounds(New Rect(New Point(0, 0), Element.RenderSize))) Then Return
  27. '执行
  28. Handled = True
  29. CType(e.NewValue, Action).Invoke()
  30. RemoveHandler Element.LayoutUpdated, Handler
  31. End Sub
  32. AddHandler Element.LayoutUpdated, Handler
  33. End Sub
  34. Private Function FindParentScrollViewer(d As DependencyObject) As ScrollViewer
  35. While d IsNot Nothing
  36. If TypeOf d Is ScrollViewer Then Return CType(d, ScrollViewer)
  37. d = VisualTreeHelper.GetParent(d)
  38. End While
  39. Return Nothing
  40. End Function
  41. End Module