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

时间:2012-12-07 17:43:23

标签: c# windows-phone-7 xaml

我知道这个问题已在这里提出,但没有回答。所以我再问一次,但就此提出我自己的调查,看看能否解决这个问题。

问题

我们有一个数据绑定ListBox。我希望它在我向数据源添加新元素时保留视口(正在显示的元素)。这样,我可以在不改变视图的情况下添加新元素。

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

可能的解决方案

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

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

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

  • 计算要添加的所有元素的垂直大小以补偿垂直偏移。这似乎是一个很好的解决方案(我正在调查它),但我担心它也会产生“跳跃”效应。这将覆盖列表框中的PrepareContainerForItemOverride方法。当基本方法已经准备好容器时,获取其高度并将其添加到计数器中。然后,当负载完成时,滚动到获得的垂直偏移。它不可能连续地执行(我们只能调用ScrollToVerticalOffset方法,它不会立即滚动)所以我认为这不会成为最终的解决方案。

我的猜测是,要实现这一点,我们应该深入研究Listbox定义。在某处,Listbox管理ItemsSource属性的CollectionChanged事件。在那里,列表决定重新创建缓冲区(more on Listbox buffers here)。由于这些依赖于ScrollViewer的VerticalOffset属性(常量),视口会发生变化。我们应该修改Listbox,这样它就不会重新创建缓冲区。问题是我对如何做到这一点没有任何线索。

对此有什么想法吗?

谢谢!

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

1 个答案:

答案 0 :(得分:-2)

您应ObservableCollection使用ItemsSource ListBox作为ObservableCollection。因此,无论何时向ListBox添加对象,ObservableCollection都会保留其视图。神奇的是INotifyPropertyChanged实现了{{1}}接口

请参阅How to use ObservableCollection

请参阅How to use INotifyPropertyChanged interface