使用依赖属性实现监视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);            }        }    }
稍后添加注释.