WP7 ListBox 滚动探测 以及 分页加载

  LIST BOX 真心有点蛋疼。。。  滚来滚去 你就是不知掉 他滚在那里 。。。 对于 在移动 设备上经常需要使用 列表 并且 滚动加载  这可蛋疼 。
编辑过 Listbox 的template 人肯定知道  ListBox 里面的主体是个ScrollView构成的 ,我们来看看 这个 ScrollView 。。。

唔。。。 里面 额 。。 有两个东西
VerticalOffset
HorizontalOffset

这两个分别可以获取 垂直和水平方向上的滚动位置 。。。

(其实 ScrollView 里面是有两个 ScrollBar ScrollBar有Value Change 事件 ,可以挖出 ScrollBar 找到 事件 并订阅的,, 。。。。)

现在我们第一定出我们的策略 就是 挖出 ScrollView 然后 监听 VerticalOffset  当 VeritcalOffset 到最大值的时候 就可以发出一个滚动到底部的通知?! 事件?! 无所谓了。。。

好吧 直接上代码

 代码如下 复制代码

public class ScrollBehavior
    {
        public static DependencyProperty AtEndCommandProperty
            = DependencyProperty.RegisterAttached(
                "AtEndCommand", typeof(ICommand),
                typeof(ScrollBehavior),
                new PropertyMetadata(null, OnCommandChanged));

        public static ICommand GetAtEndCommand(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(AtEndCommandProperty);
        }

        public static void SetAtEndCommand(DependencyObject obj, ICommand value)
        {
            obj.SetValue(AtEndCommandProperty, value);
        }

        public static DependencyProperty AtTopCommandProperty
           = DependencyProperty.RegisterAttached(
               "AtTopCommand", typeof(ICommand),
               typeof(ScrollBehavior),
               new PropertyMetadata(null, OnCommandChanged));

        public static ICommand GetAtTopCommand(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(AtTopCommandProperty);
        }

        public static void SetAtTopCommand(DependencyObject obj, ICommand value)
        {
            obj.SetValue(AtTopCommandProperty, value);
        }

        public static DependencyProperty AtScrollCommandProperty
        = DependencyProperty.RegisterAttached(
       "AtScrollCommand", typeof(ICommand),
       typeof(ScrollBehavior),
       new PropertyMetadata(null, OnCommandChanged));

        public static ICommand GetAtScrollCommand(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(AtScrollCommandProperty);
        }

        public static void SetAtScrollCommand(DependencyObject obj, ICommand value)
        {
            obj.SetValue(AtScrollCommandProperty, value);
        }

 

        public static void OnCommandChanged(
            DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)d;
            if (element != null && element is ListBox)
            {
                element.Loaded -= element_Loaded;
                element.Loaded += element_Loaded;
            }
        }

        static void element_Loaded(object sender, RoutedEventArgs e)
        {
            ((FrameworkElement)sender).Loaded -= element_Loaded;
            ScrollViewer scrollViewer = FindChildOfType<ScrollViewer>((FrameworkElement)sender);
            if (scrollViewer != null)
            {

                var listener = new Listener();
                listener.Changed += delegate
                {

                    if (scrollViewer.ScrollableHeight != 0)
                    {
                        //System.Diagnostics.Debug.WriteLine((scrollViewer.VerticalOffset - scrollViewer.ScrollableHeight).ToString());
                        if ((scrollViewer.VerticalOffset - scrollViewer.ScrollableHeight) >= -2)
                        {

                            CommandArg endCommandArg = new CommandArg();
                            endCommandArg.Key = "IsEnd";
                            endCommandArg.Value = true;

                            var endCommand = GetAtEndCommand((FrameworkElement)sender);

                            if (endCommand != null && endCommand.CanExecute(endCommandArg))
                            {
                                //System.Diagnostics.Debug.WriteLine("Scroll End");
                                endCommand.Execute(endCommandArg);
                            }
                        }

                        //System.Diagnostics.Debug.WriteLine(scrollViewer.VerticalOffset.ToString());
                        if (scrollViewer.VerticalOffset < 2)
                        {
                            CommandArg topCommandArg = new CommandArg();
                            topCommandArg.Key = "IsEnd";
                            topCommandArg.Value = false;

                            var topCommand = GetAtTopCommand((FrameworkElement)sender);
                            if (topCommand != null && topCommand.CanExecute(topCommandArg))
                            {

                                //System.Diagnostics.Debug.WriteLine("Scroll Top");
                                topCommand.Execute(topCommandArg);
                            }
                        }

                        CommandArg scrollCommandArg = new CommandArg();
                        scrollCommandArg.Key = "Sender";
                        scrollCommandArg.Value = scrollViewer;

                        var scrollCommand = GetAtScrollCommand((FrameworkElement)sender);
                        if (scrollCommand != null && scrollCommand.CanExecute(scrollCommandArg))
                        {
                            //System.Diagnostics.Debug.WriteLine("Scroll");
                            scrollCommand.Execute(scrollCommandArg);
                        }
                    }

                };

                Binding binding = new Binding("VerticalOffset");
                binding.Source = scrollViewer;
                listener.Attach(scrollViewer, binding);

            }

        }

        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;
        }
    }

    public class Listener
    {
        public readonly DependencyProperty property;
        ScrollViewer target;

        public Listener()
        {
            property = DependencyProperty.RegisterAttached(
                "ListenValue",
                typeof(object),
                typeof(Listener),
                new PropertyMetadata(null, HandleValueChanged));
        }

        public event EventHandler<ValueChangedEventArgs> Changed;

        void HandleValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {

            OnChanged(new ValueChangedEventArgs(e));
        }

        protected void OnChanged(ValueChangedEventArgs e)
        {

            if (Changed != null)
            {
                Changed(target, e);
            }
        }

        public void Attach(ScrollViewer element, Binding binding)
        {
            if (target != null)
            {
                throw new Exception(
                    "Cannot attach an already attached listener");
            }

            target = element;
            if (target.GetBindingExpression(property) == null)
            {
                target.SetBinding(property, binding);
            }

        }

        public void Detach()
        {
            target.ClearValue(property);
            target = null;
        }

    }

    public class ValueChangedEventArgs : EventArgs
    {
        public ValueChangedEventArgs(DependencyPropertyChangedEventArgs e)
        {
            EventArgs = e;
        }

        public DependencyPropertyChangedEventArgs EventArgs { get; private set; }
    }

  我先做了三个ICommand  类型的动态 属性 分别是 滚动到顶部 底部 和滚动中 所调用的Command

然后在动态属性绑定时 订阅控件 Loaded事件 ,这样 空间一旦Loaded 就我们就去翻出ScrollView 然后的 Listener 去监听 他的 VerticalOffset

监听器 其实就是做了个动态属性的Listener ,我们只需要把 ScrollView.VerticalOffset 绑定到 这个 Listener 的动态属性上 ,这样当值一旦变化 就会调用 方法HandleValueChanged

时间: 2024-09-10 06:13:37

WP7 ListBox 滚动探测 以及 分页加载的相关文章

Android实现基于滑动的SQLite数据分页加载技术(附demo源码下载)_Android

本文实例讲述了Android实现基于滑动的SQLite数据分页加载技术.分享给大家供大家参考,具体如下: main.xml如下: <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/action_settings" android:orderInCategory="100" android:showAs

Android应用中ListView利用OnScrollListener分页加载数据_Android

当用户从网络上读取微薄的时候,如果一下子全部加载用户未读的微薄这将耗费比较长的时间,造成不好的用户体验,同时一屏的内容也不足以显示如此多的内容.这时候,我们就需要用到另一个功能,那就是listview的分页了.通过分页分次加载数据,用户看多少就去加载多少. 通常这也分为两种方式,一种是设置一个按钮,用户点击即加载.另一种是当用户滑动到底部时自动加载.今天我就和大家分享一下这个功能的实现. 首先,写一个xml文件,moredata.xml,该文件即定义了放在listview底部的视图: <?xml

Android程序开发之Listview下拉刷新上拉(滑动分页)加载更多_Android

最近做的类似于微博的项目中,有个Android功能要使用到listview的向下拉刷新来刷新最新消息,向上拉刷新(滑动分页)来加载更多. 新浪微博就是使用这种方式的典型. 当用户从网络上读取微博的时候,如果一下子全部加载用户未读的微博这将耗费比较长的时间,造成不好的用户体验,同时一屏的内容也不足以显示如此多的内容.这时候,我们就需要用到另一个功能,那就是listview的分页了,其实这个分页可以做成客户端的分页,也可以做成服务器端的分页(点击加载时,从服务器对应的加载第N页就好了!!!).通过分

Android基于ListView实现类似Market分页加载效果示例_Android

本文实例讲述了Android基于ListView实现类似Market分页加载效果.分享给大家供大家参考,具体如下: 最近几天研究ListView实现分页加载和滚动加载,发现可以用listView的OnScroll方法来实现,直接上代码 ListViewScroll.java package zy.lucifer.ListViewScroll; import android.app.Activity; import android.os.Bundle; import android.util.Lo

Android之ListView分页加载数据功能实现代码

什么是ListView分页加载数据功能呢?在现在的大数据时代,我们不可能把某些数据全部展示到界面,好比我们经常会看的QQ空间一样,当你看动态的时候,系统不可能会把所有好友的动态都展示在上面,你能看到的一般都是最新好友更新的动态,假如你要看非最新的好友动态,通常你都会手指向上滑动屏幕然后去查看,当界面下滑到一定数量的时候,就会看到一个"查看更多",然后突然停顿一下,系统会通过网络去给你刷新其他动态信息,这样的功能我们一般叫做数据下拉刷新功能,也就是我们的分页加载功能,具体的实现是怎样的呢

Android程序开发之Listview下拉刷新上拉(滑动分页)加载更多

最近做的类似于微博的项目中,有个Android功能要使用到listview的向下拉刷新来刷新最新消息,向上拉刷新(滑动分页)来加载更多. 新浪微博就是使用这种方式的典型. 当用户从网络上读取微博的时候,如果一下子全部加载用户未读的微博这将耗费比较长的时间,造成不好的用户体验,同时一屏的内容也不足以显示如此多的内容.这时候,我们就需要用到另一个功能,那就是listview的分页了,其实这个分页可以做成客户端的分页,也可以做成服务器端的分页(点击加载时,从服务器对应的加载第N页就好了!!!).通过分

Android实现基于滑动的SQLite数据分页加载技术(附demo源码下载)

本文实例讲述了Android实现基于滑动的SQLite数据分页加载技术.分享给大家供大家参考,具体如下: main.xml如下: <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/action_settings" android:orderInCategory="100" android:showAs

Android基于ListView实现类似Market分页加载效果示例

本文实例讲述了Android基于ListView实现类似Market分页加载效果.分享给大家供大家参考,具体如下: 最近几天研究ListView实现分页加载和滚动加载,发现可以用listView的OnScroll方法来实现,直接上代码 ListViewScroll.java package zy.lucifer.ListViewScroll; import android.app.Activity; import android.os.Bundle; import android.util.Lo

jQuery结合AJAX之在页面滚动时从服务器加载数据

  这篇文章主要介绍了jQuery结合AJAX之在页面滚动时从服务器加载数据,文中示例服务器端为C#程序,需要的朋友可以参考下 简介 文本将演示怎么在滚动滚动条时从服务器端下载数据.用AJAX技术从服务器端加载数据有助于改善任何web应用的性能表现,因为在打开页面时,只有一屏的数据从服务器端加载了,需要更多的数据时,可以随着用户滚动滚动条再从服务器端加载. 背景 是Facebook促使我写出了在滚动条滚动时再从服务器加载数据的代码.浏览facebook时,我很惊讶的发现当我滚动页面时,新的来自服