【问题标题】:WP7 Auto Grow ListBox upon reaching the last item到达最后一项时WP7自动增长列表框
【发布时间】:2010-12-16 01:08:12
【问题描述】:

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

这在 WP7 中是否可行?

编辑:另一种说法是,我们能否检测到列表何时“反弹”?

【问题讨论】:

    标签: c# silverlight windows-phone-7 listbox scroll


    【解决方案1】:

    Daniel Vaughan 在http://danielvaughan.orpius.com/post/Scroll-Based-Data-Loading-in-Windows-Phone-7.aspx 发布了一个如何检测此问题的示例

    【讨论】:

    • 不幸的是,这会导致内存泄漏,如support.microsoft.com/kb/938416 中所述。结果是使用这种技术的页面不会被 GC 释放。
    • @Agent_L - 你知道 Windows Phone 8 是否解决了这个问题吗?我不能说我理解它,但我刚刚在他的 W8 中实现了 Daniel Vaughans 的新版本,并想确保我不会在这里错过任何东西。
    • @Jimmyt1988 我不知道,我使用其他解决方案。恕我直言,所有基于达到确切滚动结束的概念都是有缺陷的。用户可能几乎滚动到最后,因此永远不会触发加载操作。我正在使用添加到列表末尾的额外项目,它一直显示“正在加载”,并且这个项目进入视野(get 被虚拟化列表上的 UI 调用)触发加载更多数据。它有两个好处:立即通知用户列表正在加载,并且加载操作实际上发生在它出现之前的一段时间。所以在快速连接时,用户永远看不到项目跳入。
    【解决方案2】:

    这并不容易,因为有很多活动部件,但这是你可以做的,假设你想要一个简短的列表,当你向下滚动时从你的数据中加载更多,类似于很多推特应用等。

    • 编写您自己的 ObservableCollection 子类,该子类仅提供少数项目(如 20 个),将其余项目保留到请求为止
    • 挂钩滚动查看器(在列表框或容器内)及其视觉状态改变事件,可以得到NotScrolling和Scrolling的变化;例如see this code by ptorr
    • 当滚动停止时,使用viewer scroll extensions code 查看扩展的位置(在底部与否)或仅使用原始滚动查看器属性查看它是否扩展到底部
    • 如果是这样,请触发您的可观察集合以释放另一组项目。

    抱歉,我还没有准备好写博客的完整示例。祝你好运!

    【讨论】:

      【解决方案3】:

      我刚刚为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 - 我确信有更好的方法......

      【讨论】:

        【解决方案4】:

        看看这个来自 msdn 博客的detect Listbox compression state

        【讨论】:

          【解决方案5】:

          【讨论】:

          • 不幸的是,这不是正在寻找的效果。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多