c# - 如何在 WP Listbox 上保留视口(viewport)(滚动位置)?

标签 c# windows-phone-7 xaml

我知道这里已经有人问过这个问题,但没有人回答。所以我再次询问,但提供我自己的调查,看看我们是否可以解决这个问题。

问题

我们有一个数据绑定(bind)列表框。当我向数据源添加新元素时,我希望它保留视口(viewport)(正在显示的元素)。这样,我可以在不更改 View 的情况下添加新元素。

当前的 WP 行为是保留滚动位置(ScrollViewer.VerticalOffset 是常量)。这样,当您添加新元素时,所有元素都会下降。

可能的解决方案

我一直在挖掘这个,我有一些线索。

  • 当列表不在顶部时禁用数据源刷新。这样,我们可以在不更改视口(viewport)的情况下添加新项目。问题:当用户再次回到顶部时,所有新元素突然出现在列表顶部,从而失去连续性。

  • 获取当前正在查看的项目,并在添加所有新元素后使用 ScrollIntoView 恢复它。乍一看,这似乎是最好的选择,但请相信我,事实并非如此。首先,获取当前正在查看的项目并不容易:可以使用 LinqToVisualTree 来完成。但它并不准确(你只能猜测,视口(viewport)缓冲区的大小不是恒定的)所以我们不会恢复用户之前的确切位置。而且这个解决方案会“跳转”:从用户的角度来看会有两个滚动事件,这并不好。

  • 计算添加的所有元素的垂直尺寸以补偿垂直偏移。这似乎是一个很好的解决方案(我目前正在研究它),但我担心它也会产生那种“跳跃”的效果。它将通过覆盖 Listbox 中的 PrepareContainerForItemOverride 方法来完成。当基本方法已经准备好容器时,获取它的高度并将其添加到计数器中。然后,当加载完成后,滚动到获得的垂直偏移。不可能连续这样做(我们只能调用 ScrollToVerticalOffset 方法,它不会立即滚动)所以我认为这不会成为最终的解决方案。

我的猜测是,要实现这一点,我们应该深入研究列表框定义。在某处,列表框管理 ItemsSource 属性的 CollectionChanged 事件。在那里,列表决定重新创建缓冲区(more on Listbox buffers here)。由于这些取决于 ScrollViewer 的 VerticalOffset 属性(常量),因此视口(viewport)会发生变化。我们应该修改列表框,这样它就不会重新创建缓冲区。问题是我不知道如何执行此操作。

对此有什么想法吗?

谢谢!

编辑:很明显,我正在使用 ObservableCollection 添加项目。我没有刷新 ItemsSource 属性本身。

最佳答案

您应该使用 ObservableCollection 作为 ListBoxItemsSource。因此,无论何时将对象添加到 ObservableCollectionListBox 都会保留其 View 。神奇之处在于 ObservableCollection 实现了 INotifyPropertyChanged 接口(interface)

参见 How to use ObservableCollection

参见 How to use INotifyPropertyChanged interface

关于c# - 如何在 WP Listbox 上保留视口(viewport)(滚动位置)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13768280/

相关文章:

c# - 如何关闭在 WPF 中用作子菜单的弹出窗口

c# - 并行编程互锁 C#

c# - ListBox SelectionChanged WP7 使用参数导航

c# - 是否可以在绑定(bind)功能执行之前执行辅助方法?

c# - 与资源字典共享项目 (xaml)

c# - 如何使用 C# xaml 以编程方式设置数据绑定(bind)

c# - 标记代码的属性

list - 您如何获得像闹钟中显示的那种列表选择器?

c# - 我们如何在没有动画的情况下显示 hubtile

c# - 使用 xaml 或 C# 创建灯光动画