WP7 ListBox滚动加载数据

曾将找到过关于 ListBox滚动加载数据的文章,但是现在去查找的时候,发现找不到那些文章了。不过,意外的找到一篇更好的有关ListBox滚动加载数据的帖子http://social.msdn.microsoft.com/Forums/zh-CN/windowsphonezhchs/thread/4b9ebac8-e1c1-4522-9f11-5e0567f95182 中找到的 http://www.bbniu.com/thread-1569-1-1.html,为了避免下次找不到该文章和方便查看内容,下面附上该篇文章所有的内容:

 本示例的主要目的是实现ListBox滚动加载数据。假设,默认为30条数据,当滚动到底部的时候便再次加载20条数据,以此类推。
         需要解决的问题:如何判断滚动到底部,以及处理加载数据的请求?

         思路如下:
         1.检测ListBox中的ScrollViewer控件状态。
         2.若状态不为滚动中:根据ScrollViewer的ExtentHeight与VerticalOffset,判断是否到底,并执行请求加载数据。
       

       一、添加视图状态检测代码

       首先,在XAML中添加一个空的ListBox,如下:

      




      XAML添加完成后,在后台代码中实现检测ListBox的ScrollViewer状态改变的代码,在这个步骤中需要另外2个方法 :

     1.根据视图树查找指定对象视图树中的元素  代码如下:
     



    2.根据给定元素和状态名,查找到元素中的视图状态。代码如下:
   


  
   具有这2个方法后,再来创建一个向ListBox添加数据的方法。代码如下:
   



  那么,做完准备工作了。下面注册页面Load事件,并在事件中使用以上方法,来实现我们的目的。代码如下:
  




二、如何判断ListBox滚动的位置

  在代码中已经实现了关键步骤,即捕捉到ListBox包含的ScrollViewer视图状态更改事件。

那么下面我们需要解决的问题就是如何判断是否滚动到底部,以及判断是否处于滚动中,来添加数据了。

解决这个问题需要知道ScrollViewer的几个属性:

     1.ExtentHeight       获取 ScrollViewer 中显示的所有内容的垂直大小。(总数)
     2.VerticalOffset      获取一个值,该值包含滚动内容的垂直偏移量。 (滚动到第几个)
     3.ViewportHeight  获取一个值,该值包含可见内容的垂直大小。 (页面能显示几个)

    知道这几个值的意思,那么就可以计算出当前滚动的位置了:

   



  默认为ListBox添加30条数据,执行后运行的效果,通过几个运行效果来看看:

  初始效果:
  



  下面是滚动过程中:
  




  可以看到,ExtentHeight=30,当前VerticalOffset=10.5。并没有滚动到底部。  
  继续滚动。
  



  此时已经滚动到底部,添加Item代码已经执行,实际上此时的为ExtentHeight=50。
  




  三、结尾

  ListBox动态加载数据已经完成了。那么这个实现有什么问题呢?
  1.假如数据来自服务器,存在异步延迟,并且耗时的操作会影响UI线程?
  2.避免 在异步加载过程中多次滚动到底的请求。

参考连接
----------------------------------------------------------------
1.Windows Phone Mango change, Listbox: How to detect compression(end of scroll) states ?
2.How to detect when a list is scrolling (or not)
 

a.之前找到的是关于listBox滚动到底加载数据,用的是下面这个方法(后面的注释是我猜测原来作者的意思):

private childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject

{

    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)           

       {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);//寻找obj的视图树下的子元素
                if (child != null && child is childItem)//寻找给定的子元素类型childItem,符合则返回。
                    return (childItem)child;
                else//不符合则重复函数FindVisualChild<childItem>(child);来查找,直到找到匹配函数中给定的子元素类型
                {
                    childItem childOfChild = FindVisualChild<childItem>(child);
                    if (childOfChild != null)
                        return childOfChild;
                }

     }
}

存在的问题:1)该函数一开始就寻找obj的子元素,然后再用这个子元素去寻找匹配的子元素类型,对于像scrollViewer这类控件寻找scrollviewer,就始终会使结果处于null;2)而且一旦if…else…,childItem childOfChild = FindVisualChild<childItem>(child);循环一次继续查找,如果再找不到,那么得到的最终值就是null。for循环写在这里没什么用。

b.这篇文章就有一个很好的方法:

private childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject

{

      while (obj != null)
            {
                if (obj is childItem)
                    return obj as childItem;

                obj = VisualTreeHelper.GetChild(obj, 0);
            }
            return null;

}

很好地解决了a产生的问题。1)直接开始寻找匹配的子元素类型,就不存在有些控件的直接子元素就是要找的子元素类型。如果第一层子元素找不到,那么VisualTreeHelper.GetChild(obj, 0);获取下一层的子元素,然后继续查找匹配的子元素类型;2)nullwhile (obj != null)表明该函数基本上就不会返回null,会一直匹配查找,直到查找到。

 

关于是listBox拉到底还是拉动一部分就产生操作,就需要根据需求不同来决定了。根据listBoxVisual的滚动状态StateGroup group = MainBean.FindVisualState(element, "ScrollStates");和group.CurrentStateChanged 事件来判断。scrollViewer.VerticalOffset获取现在滚动条拉动的高度。scrollViewer.VerticalOffset >= scrollViewer.ScrollableHeight(滚动到底,滚动条>实际可滚动高度);ListBox滚动加载数据

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值