使用依赖属性实现监视ListBox滚动到底部

前端之家收集整理的这篇文章主要介绍了使用依赖属性实现监视ListBox滚动到底部前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
  1. //自定义依赖属性用来监视ListBox滚动到底事件
  2. public class ListBoxScrollToBottomNotify
  3. {
  4. public static ICommand GetScrollToBottomCommand(DependencyObject obj)
  5. {
  6. return (ICommand)obj.GetValue(ScrollToBottomCommandProperty);
  7. }
  8.  
  9. public static void SetScrollToBottomCommand(DependencyObject obj,ICommand value)
  10. {
  11. obj.SetValue(ScrollToBottomCommandProperty,value);
  12. }
  13.  
  14. //滚动到底问时响应的事件
  15. public static readonly DependencyProperty ScrollToBottomCommandProperty =
  16. DependencyProperty.RegisterAttached("ScrollToBottomCommand",typeof(ICommand),typeof(ListBoxScrollToBottomNotify),new PropertyMetadata(null,OnCommandChanged));
  17.  
  18. static void OnCommandChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
  19. {
  20. ListBox lb = d as ListBox;
  21. if (lb != null)
  22. {
  23. //确定只绑定一次ListBox的Loaded事件
  24. if (e.OldValue == null)
  25. {
  26. lb.Loaded += new RoutedEventHandler(OnListBoxLoaded);
  27. }
  28. }
  29. }
  30. static void OnListBoxLoaded(object sender,RoutedEventArgs e)
  31. {
  32. ListBox lb = sender as ListBox;
  33. ScrollViewer scrollViewer = FindChildOfType<ScrollViewer>(lb);
  34. if (scrollViewer != null)
  35. {
  36. VerticalOffsetOfScrollViewNotify monitorVO = new VerticalOffsetOfScrollViewNotify();
  37. monitorVO.Attached(scrollViewer);
  38. monitorVO.VerticalOffsetChanged = () =>
  39. {
  40. double verticalOffset = Math.Round(scrollViewer.VerticalOffset);
  41. double scrollableHeight = Math.Round(scrollViewer.ScrollableHeight);
  42. if (verticalOffset >= scrollableHeight)
  43. {
  44. ICommand command= GetScrollToBottomCommand(lb);
  45. command.Execute(null);
  46. }
  47. };
  48. }
  49. }
  50. //获取子类型
  51. static T FindChildOfType<T>(DependencyObject root) where T : class
  52. {
  53. var queue = new Queue<DependencyObject>();
  54. queue.Enqueue(root);
  55.  
  56. while (queue.Count > 0)
  57. {
  58. DependencyObject current = queue.Dequeue();
  59. for (int i = VisualTreeHelper.GetChildrenCount(current) - 1; 0 <= i; i--)
  60. {
  61. var child = VisualTreeHelper.GetChild(current,i);
  62. var typedChild = child as T;
  63. if (typedChild != null)
  64. {
  65. return typedChild;
  66. }
  67. queue.Enqueue(child);
  68. }
  69. }
  70. return null;
  71. }
  72. }
  73. //监测ListBox中ScrollView的VerticalOffset改变
  74. public class VerticalOffsetOfScrollViewNotify
  75. {
  76. //通过监控ListBox的MouseMove事件和ManipulationCompleted事件的效果并不好,//当手指在屏幕上划动后ListBox会因为惯性,再滚动一段距离.这样使用前两个事件就不能判断滚动的最后位置
  77. //现在改成通过依赖属性绑定到ListBox的ScrollView的VerticalOffset来实现
  78. DependencyProperty VerticalOffsetProperty;
  79.  
  80. public VerticalOffsetOfScrollViewNotify()
  81. {
  82. VerticalOffsetProperty = DependencyProperty.RegisterAttached("VerticalOffset",typeof(double),typeof(VerticalOffsetOfScrollViewNotify),new PropertyMetadata(OnVerticalOffsetChanged));
  83. }
  84. public void OnVerticalOffsetChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
  85. {
  86. if (VerticalOffsetChanged != null)
  87. {
  88. VerticalOffsetChanged();
  89. }
  90. }
  91.  
  92. public Action VerticalOffsetChanged { get; set; }
  93. public void Attached(FrameworkElement ele)
  94. {
  95. if (ele != null)
  96. {
  97. ScrollViewer scrollViewer = ele as ScrollViewer;
  98. Binding binding = new Binding("VerticalOffset") { Source = scrollViewer };
  99. scrollViewer.SetBinding(VerticalOffsetProperty,binding);
  100. }
  101. }
  102. }
稍后添加注释.

猜你在找的设计模式相关文章