使用依赖属性实现监视ListBox滚动到底部
来源:互联网 发布:阿里云服务器重做系统 编辑:程序博客网 时间:2024/06/05 17:24
//自定义依赖属性用来监视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); } } }
稍后添加注释.