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

C# 如何在WP Listbox上保留视口(滚动位置)?,c#,windows-phone-7,xaml,C#,Windows Phone 7,Xaml,我知道这里已经有人问过这个问题,但没有人回答。所以我再次询问,但提供我自己的调查,看看我们是否能解决这个问题 问题 我们有一个数据绑定列表框。在向数据源添加新元素时,我希望它保留视口(正在显示的元素)。这样,我就可以添加新元素而不必更改视图 当前WP行为为保留滚动位置(ScrollViewer.VerticalOffset为常量)。这样,当您添加新元素时,所有元素都会下降 可能的解决方案 我已经为此挖掘了很多,我有一些线索 当列表不在顶部时禁用数据源刷新。这样,我们可以在不更改视口的情况下添加

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

问题

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

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

可能的解决方案

我已经为此挖掘了很多,我有一些线索

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

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

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

我的猜测是,为了实现这一点,我们应该深入研究列表框定义。在某些地方,Listbox管理ItemsSource属性的CollectionChanged事件。在这里,列表决定重新创建缓冲区()。由于这些取决于ScrollViewer的VerticalOffset属性(常数),视口将发生变化。我们应该修改列表框,使其不会重新创建缓冲区。问题是我不知道该怎么做

有什么想法吗

谢谢


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

您应该将
ObservableCollection
作为
ItemsSource
用于
列表框
。因此,无论何时将对象添加到
可观察集合
列表框
都将保留其视图。神奇的是,
observetecollection
实现了
INotifyPropertyChanged
接口


请参见对于
列表框
,您应该使用
可观察收集
作为
项目资源
。因此,无论何时将对象添加到
可观察集合
列表框
都将保留其视图。神奇的是,
observetecollection
实现了
INotifyPropertyChanged
接口


请参见

我已经使用了ObservableCollection(这是一个线程安全的修改,但它实现了
INotifyPropertyChanged
)。这不是问题所在。当您将项目添加到该
ObservaleCollection
的顶部时,列表将保持垂直偏移,项目将向下移动。我已经使用了ObservaleCollection(这是一个线程安全的修改,但它实现了
INotifyPropertyChanged
)。这不是问题所在。当您将项目添加到该
可观察集合的顶部时,列表将保持垂直偏移,并且项目将向下移动。