使用依賴屬性實現監視ListBox滾動到底部
阿新 • • 發佈:2019-01-05
稍後添加註釋.//自定義依賴屬性用來監視ListBox滾動到底事件 public class ListBoxScrollToBottomNotify { public static ICommand GetScrollToBottomCommand(DependencyObject obj) { return (ICommand)obj.GetValue(ScrollToBottomCommandProperty); } public static void SetScrollToBottomCommand(DependencyObject obj, ICommand value) { obj.SetValue(ScrollToBottomCommandProperty, value); } //滾動到底問時響應的事件 public static readonly DependencyProperty ScrollToBottomCommandProperty = DependencyProperty.RegisterAttached("ScrollToBottomCommand", typeof(ICommand), typeof(ListBoxScrollToBottomNotify), new PropertyMetadata(null, OnCommandChanged)); static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ListBox lb = d as ListBox; if (lb != null) { //確定只繫結一次ListBox的Loaded事件 if (e.OldValue == null) { lb.Loaded += new RoutedEventHandler(OnListBoxLoaded); } } } static void OnListBoxLoaded(object sender, RoutedEventArgs e) { ListBox lb = sender as ListBox; ScrollViewer scrollViewer = FindChildOfType<ScrollViewer>(lb); if (scrollViewer != null) { VerticalOffsetOfScrollViewNotify monitorVO = new VerticalOffsetOfScrollViewNotify(); monitorVO.Attached(scrollViewer); monitorVO.VerticalOffsetChanged = () => { double verticalOffset = Math.Round(scrollViewer.VerticalOffset); double scrollableHeight = Math.Round(scrollViewer.ScrollableHeight); if (verticalOffset >= scrollableHeight) { ICommand command= GetScrollToBottomCommand(lb); command.Execute(null); } }; } } //獲取子型別 static T FindChildOfType<T>(DependencyObject root) where T : class { var queue = new Queue<DependencyObject>(); queue.Enqueue(root); while (queue.Count > 0) { DependencyObject current = queue.Dequeue(); for (int i = VisualTreeHelper.GetChildrenCount(current) - 1; 0 <= i; i--) { var child = VisualTreeHelper.GetChild(current, i); var typedChild = child as T; if (typedChild != null) { return typedChild; } queue.Enqueue(child); } } return null; } } //監測ListBox中ScrollView的VerticalOffset改變 public class VerticalOffsetOfScrollViewNotify { //通過監控ListBox的MouseMove事件和ManipulationCompleted事件的效果並不好, //當手指在螢幕上划動後ListBox會因為慣性,再滾動一段距離.這樣使用前兩個事件就不能判斷滾動的最後位置 //現在改成通過依賴屬性繫結到ListBox的ScrollView的VerticalOffset來實現 DependencyProperty VerticalOffsetProperty; public VerticalOffsetOfScrollViewNotify() { VerticalOffsetProperty = DependencyProperty.RegisterAttached("VerticalOffset", typeof(double), typeof(VerticalOffsetOfScrollViewNotify), new PropertyMetadata(OnVerticalOffsetChanged)); } public void OnVerticalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (VerticalOffsetChanged != null) { VerticalOffsetChanged(); } } public Action VerticalOffsetChanged { get; set; } public void Attached(FrameworkElement ele) { if (ele != null) { ScrollViewer scrollViewer = ele as ScrollViewer; Binding binding = new Binding("VerticalOffset") { Source = scrollViewer }; scrollViewer.SetBinding(VerticalOffsetProperty, binding); } } }