当WP7 ListBox滚动到最后一个项目时,如何实现自动增长。

6
我正在尝试实现这样一个效果,即当用户向下滚动到最后一项时,会附加更多的项目到列表中。我还没有找到一种方法来确定用户是否已经滚动到了列表的末尾。我没有看到 ListBox 上触发的事件,告诉我用户何时到达列表底部。如果有一些东西告诉我何时滚动到视图中的项目,那就太好了,但据我所知,没有这样的东西。

在WP7中,这种效果是否可行?

编辑:另一种表述方式是,我们能否检测到列表已经“弹回”?

5个回答

7

Daniel Vaughan在这里发布了一个示例,展示如何检测Windows Phone 7中的滚动数据加载。


不幸的是,这会导致内存泄漏,如http://support.microsoft.com/kb/938416所述。 结果是使用此技术的页面将不会被GC释放。 - Agent_L
@Agent_L - 你知道Windows Phone 8的这个问题是否已经解决了吗?我不太理解,但我刚刚在Daniel Vaughans的W8 unleashed中实现了他的新版本,并想确保我没有错过什么。 - Jimmyt1988
@Jimmyt1988 我不清楚,我使用其他解决方案。在我看来,所有基于到达准确滚动末尾的概念都是有缺陷的。用户可能会滚动到几乎末尾,从而永远不会触发加载操作。我使用额外的项目添加到列表末尾,始终显示“正在加载”,并且这个项目进入视图(get 在虚拟化列表上由 UI 调用)会触发加载更多数据。它有两个好处:用户立即得知列表正在加载,并且加载操作实际上发生在它进入视图之前的某个时间。因此,在高速连接上,用户永远看不到条目跳动。 - Agent_L

5

我刚刚为Overflow7实现了这个功能。

我采用的方法类似于http://blog.slimcode.com/2010/09/11/detect-when-a-listbox-scrolls-to-its-end-wp7/

不过,我没有使用样式,而是在代码中进行了钩子连接。

基本上,我将父UserControl派生自:

    public class BaseExtendedListUserControl : UserControl
{
    DependencyProperty ListVerticalOffsetProperty = DependencyProperty.Register(
      "ListVerticalOffset",
      typeof(double),
      typeof(BaseExtendedListUserControl),
      new PropertyMetadata(new PropertyChangedCallback(OnListVerticalOffsetChanged)));

    private ScrollViewer _listScrollViewer;

    protected void EnsureBoundToScrollViewer()
    {
        if (_listScrollViewer != null)
            return;

        var elements = VisualTreeHelper.FindElementsInHostCoordinates(new Rect(0,0,this.Width, this.Height), this);

        _listScrollViewer = elements.Where(x => x is ScrollViewer).FirstOrDefault() as ScrollViewer;

        if (_listScrollViewer == null)
            return;

        Binding binding = new Binding();
        binding.Source = _listScrollViewer;
        binding.Path = new PropertyPath("VerticalOffset");
        binding.Mode = BindingMode.OneWay;
        this.SetBinding(ListVerticalOffsetProperty, binding);
    }

    public double ListVerticalOffset
    {
        get { return (double)this.GetValue(ListVerticalOffsetProperty); }
        set { this.SetValue(ListVerticalOffsetProperty, value); }
    }

    private static void OnListVerticalOffsetChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        BaseExtendedListUserControl control = obj as BaseExtendedListUserControl;
        control.OnListVerticalOffsetChanged();
    }

    private void OnListVerticalOffsetChanged()
    {
        OnListVerticalOffsetChanged(_listScrollViewer);

    }

    protected virtual void OnListVerticalOffsetChanged(ScrollViewer s)
    {
        // do nothing
    }
}

这意味着在用户控件本身中,我可以使用以下内容:
        protected override void OnListVerticalOffsetChanged(ScrollViewer viewer)
    {
        // Trigger when at the end of the viewport
        if (viewer.VerticalOffset >= viewer.ScrollableHeight)
        {
            if (MoreClick != null)
            {
                MoreClick(this, new RoutedEventArgs());
            }
        }
    }

    private void ListBox1_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
    {
        EnsureBoundToScrollViewer();
    }

这里的“hacky”方法是我必须使用ListBox1_ManipulationCompleted和VisualTreeHelper来找到我的ScrollViewer - 我相信有更好的方法...

5
这并不是一件非常容易的事情,因为有很多要考虑的因素,但假设你想要一个类似于许多Twitter应用程序等的短列表,随着向下滚动加载更多数据,那么你可以这样做:
  • 编写自己的ObservableCollection子类,只提供少量项目(例如20个),保留其余部分直到被请求
  • 连接到滚动查看器(在listbox或容器内)及其可视状态更改事件,您可以获取NotScrolling和Scrolling更改;例如,请参见ptorr的此代码
  • 当滚动停止时,使用viewer scroll extensions code来查看事物是否扩展(在底部还是不在底部),或者仅使用原始滚动查看器属性来查看它是否扩展到底部
  • 如果是,则触发您的observable collection以释放另一组项目。
抱歉我没有准备好完整的示例供博客使用。祝你好运!

0

-1

很不幸,这不是我们正在寻找的效果。 - Jeff Wilcox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接