2012-12-07 42 views
2

我知道这个问题已经在这里问过,但没有回答。所以我再问一次,但提供我自己的调查,看看我们是否可以解决这个问题。如何在WP Listbox上保留视口(滚动位置)?

问题

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

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

可能的解决方案

我已经挖了很多与此,我有一些线索。

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

  • 获取当前查看的项目,当所有的新元素都添加了它ScrollIntoView恢复。起初这看起来可能是最好的选择,但相信我不是。首先,获取正在查看的当前项目并不容易:它可以通过LinqToVisualTree完成,但它不完全(只能猜测它,视口缓冲区的大小不是恒定的),所以我们不会恢复用户以前的确切位置。这个解决方案会“跳跃”:从用户的角度来看,会有两个滚动事件,这并不好。

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

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

对此有何想法?

谢谢!

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

回答

-2

对于ListBox,您应该使用ObservableCollection作为ItemsSource。因此,无论何时将对象添加到ObservableCollectionListBox都将保留其视图。神奇的是,ObservableCollection实现INotifyPropertyChanged接口

How to use ObservableCollection

How to use INotifyPropertyChanged interface

+0

我已经使用的ObservableCollection(当然,修改所以它是线程安全的,但它实现了'INotifyPropertyChanged')。这不是问题。当您将项目添加到“ObservableCollection”的顶部时,该列表将保持垂直偏移,并且项目向下移动。 – gjulianm

相关问题