2

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

问题

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

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

可能的解决方案

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

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

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

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

我的猜测是,为了实现这一点,我们应该深入了解 Listbox 定义。在某处,Listbox 管理 ItemsSource 属性的 CollectionChanged 事件。在那里,列表决定重新创建缓冲区(更多关于 Listbox 缓冲区的信息)。由于这些取决于 ScrollViewer(常量)的 VerticalOffset 属性,因此视口会发生变化。我们应该修改 Listbox,使其不会重新创建缓冲区。问题是我不知道如何做到这一点。

对此有任何想法吗?

谢谢!

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

4

1 回答 1

-2

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

请参阅如何使用 ObservableCollection

请参阅如何使用 INotifyPropertyChanged 接口

于 2012-12-10T08:29:00.833 回答