首页 > 代码库 > 【WP8】ScrollViewer滑动到底触发器

【WP8】ScrollViewer滑动到底触发器

很多时候会有到底加载更多的需求,而ScrollViewer不支持继承,无法继承它进行扩展,只能通过触发器来控制到底的事件(当然,可以通过UserControl去扩展)

  思路:定义一个Trigger,自定义依赖属性,绑定到该属性到ScrollViewer的VerticalOffset属性上,然后监听属性的变化,就能监控到滚动事件了,然后判断滚动的位置从而判断出是否到底

  原理很简单,下面看实现

 

// *************************************************// // 作者:bomo// 小组:WP开发组// 创建日期:2014/7/9 0:10:32// 版本号:V1.00// 说明:// // *************************************************// // 修改历史: // Date                WhoChanges        Made // 2014/7/9 0:10:32            bomo         Initial creation //// *************************************************using System.Collections.Generic;using System.Linq;using System.Windows;using System.Windows.Media;namespace XTuOne.Common.Helpers{    /// <summary>    /// 扩展依赖属性类    /// </summary>    public static class DependencyObjectExtend    {        public static IEnumerable<DependencyObject> GetDescendant(this DependencyObject element)        {            var list = new List<DependencyObject>();            var count = VisualTreeHelper.GetChildrenCount(element);            for (int i = 0; i < count; i++)            {                var child = VisualTreeHelper.GetChild(element, i);                list.Add(child);                list.AddRange(child.GetDescendant());            }            return list;        }             /// <summary>        /// 查找子孙节点中符合类型的首个节点        /// </summary>        public static T GetFirstDescendantOfType<T>(this DependencyObject start) where T : DependencyObject        {            return start.GetDescendantsOfType<T>().FirstOrDefault();        }        /// <summary>        /// 查找子孙节点中符合类型的节点        /// </summary>        public static IEnumerable<T> GetDescendantsOfType<T>(this DependencyObject start) where T : DependencyObject        {            return start.GetDescendants().OfType<T>();        }        /// <summary>        /// 获取所有的子孙阶段        /// </summary>        public static IEnumerable<DependencyObject> GetDescendants(this DependencyObject start)        {            if (start == null)                yield break;            var queue = new Queue<DependencyObject>();            queue.Enqueue(start);            yield return start;            while (queue.Count > 0)            {                var parent = queue.Dequeue();                var count2 = VisualTreeHelper.GetChildrenCount(parent);                for (int i = 0; i < count2; i++)                {                    var child = VisualTreeHelper.GetChild(parent, i);                    yield return child;                    queue.Enqueue(child);                }            }        }    }}
依赖属性扩展类

 

// *************************************************// // 作者:bomo// 小组:WP开发组// 创建日期:2014/7/11 11:45:14// 版本号:V1.00// 说明:// // *************************************************// // 修改历史: // Date                WhoChanges        Made // 2014/7/11 11:45:14            bomo         Initial creation //// *************************************************using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Interactivity;using XTuOne.Common.Helpers;namespace XTuOne.Utility.Helpers{    /// <summary>    /// ScrollViewer到底触发器    /// </summary>    public class ScrollViewerToBottomTrigger : TriggerBase<DependencyObject>    {        public static readonly DependencyProperty VerticalOffsetProperty = DependencyProperty.Register(            "VerticalOffset", typeof(double), typeof(ScrollViewerToBottomTrigger),            new PropertyMetadata(0.0, VerticalOffsetPropertyChanged));        private ScrollViewer scrollView;        public double VerticalOffset        {            get { return (double)GetValue(VerticalOffsetProperty); }            set { SetValue(VerticalOffsetProperty, value); }        }        public static void VerticalOffsetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)        {            var behavior = d as ScrollViewerToBottomTrigger;            if (behavior != null)                behavior.OnVerticalOffsetChanged();        }        protected override void OnAttached()        {            base.OnAttached();            if (AssociatedObject is FrameworkElement)            {                (AssociatedObject as FrameworkElement).SizeChanged += control_SizeChanged;            }        }        private void control_SizeChanged(object sender, SizeChangedEventArgs e)        {            if (!(AssociatedObject is FrameworkElement))                return;            var scroll = AssociatedObject.GetFirstDescendantOfType<ScrollViewer>();            if (scroll != null)            {                AttachedScroll(scroll);                (AssociatedObject as FrameworkElement).SizeChanged -= control_SizeChanged;            }        }        private void AttachedScroll(ScrollViewer scroll)        {            if (scroll == null)                return;            scrollView = scroll;            var binding = new Binding { Source = scroll, Path = new PropertyPath("VerticalOffset") };            BindingOperations.SetBinding(this, VerticalOffsetProperty, binding);        }        private void OnVerticalOffsetChanged()        {            var scroll = scrollView;            if (scroll == null)                return;            if (scroll.ExtentHeight - scroll.VerticalOffset - scroll.ViewportHeight <= 5)            {                InvokeActions(null);            }        }    }}

通过Trigger实现,由于Trigger是一个附加元素,可以附加到任何一个符合的元素上(子孙元素包含ScrollViewer的控件),同时触发的事件可以支持绑定

 

使用(使用CM进行绑定)

<ScrollViewer x:Name="ScrollViewer">    <i:Interaction.Triggers>        <utilityHelpers:ScrollViewerToBottomTrigger>            <micro:ActionMessage MethodName="LoadMessage"/>        </utilityHelpers:ScrollViewerToBottomTrigger>    </i:Interaction.Triggers></ScrollViewer>

一个触发器只能对应触发一个事件(用于绑定),如果需要多个扩展,比如:到顶触发,滑动触发等,就需要编写多个触发器,如果这样可以考虑在UserControl扩展