我知道這個問題已經在這裏問過,但沒有回答。所以我再問一次,但提供我自己的調查,看看我們是否可以解決這個問題。如何在WP Listbox上保留視口(滾動位置)?
問題
我們有一個數據綁定列表框。我希望它在將新元素添加到數據源時保留視口(顯示的元素)。這樣,我可以在不更改視圖的情況下添加新元素。
當前WP行爲是保持滾動位置(ScrollViewer.VerticalOffset是恆定的)。這樣,當您添加新元素時,所有元素都會關閉。
可能的解決方案
我已經挖了很多與此,我有一些線索。
當列表不在頂部時禁用數據源刷新。這樣,我們可以在不更改視口的情況下添加新項目。問題是:當用戶再次登頂時,所有新元素都會突然出現在列表頂部,從而失去連續性。
獲取當前查看的項目,當所有的新元素都添加了它
ScrollIntoView
恢復。起初這看起來可能是最好的選擇,但相信我不是。首先,獲取正在查看的當前項目並不容易:它可以通過LinqToVisualTree完成,但它不完全(只能猜測它,視口緩衝區的大小不是恆定的),所以我們不會恢復用戶以前的確切位置。這個解決方案會「跳躍」:從用戶的角度來看,會有兩個滾動事件,這並不好。計算被添加的所有元素的垂直尺寸,以補償垂直偏移。這似乎是一個很好的解決方案(我目前正在調查它),但我擔心它也會產生「跳動」的效果。這將完成覆蓋Listbox中的
PrepareContainerForItemOverride
方法。當基礎方法已經準備好容器時,獲取其高度並將其添加到計數器。然後,當負載結束時,滾動到獲得的垂直偏移量。這是不可能的(我們只能稱爲ScrollToVerticalOffset
方法,它不會立即滾動),所以我認爲這不會成爲最終的解決方案。
我的猜測是,要做到這一點,我們應該深入到Listbox定義。在某處,Listbox管理ItemsSource屬性的CollectionChanged事件。在那裏,列表決定重新創建緩衝區(more on Listbox buffers here)。由於這些依賴於ScrollViewer的VerticalOffset屬性(常量),因此視口會發生變化。我們應該修改列表框,以便它不重新創建緩衝區。問題是,我不知道如何做到這一點。
對此有何想法?
謝謝!
編輯:很明顯,我正在使用ObservableCollection添加項目。我不刷新ItemsSource屬性本身。
我已經使用的ObservableCollection(當然,修改所以它是線程安全的,但它實現了'INotifyPropertyChanged')。這不是問題。當您將項目添加到「ObservableCollection」的頂部時,該列表將保持垂直偏移,並且項目向下移動。 – gjulianm