您正遇到滾動的物理滾動和邏輯之間的差異。
正如你所發現的,每一個都有其折衷。
物理滾動
物理滾動(CanContentScroll = FALSE)只是像素得好,所以:
- 視口始終表示正是您的滾動程度的相同部分,給你一個平滑滾動經驗和
但
- DataGrid的全部內容必須完全應用所有模板並進行測量和排列,以確定滾動條的大小,從而導致加載過程中的長時間延遲和高RAM使用率,並且它不會真的滾動項目所以它不理解ScrollIntoView很好
邏輯滾動
邏輯滾動(CanContentScroll =真)計算其滾動視口,並通過程度的項目,而不是像素,因此:
但
他們
之間進行選擇,這些都是隻有兩種由WPF提供滾動的。您必須根據上述折衷選擇它們。一般來說,邏輯滾動對於大中型數據集來說是最好的,而物理滾動對於小型數據集來說是最好的。
在物理滾動過程中加速加載的一個技巧是讓物理滾動更好是將您的項目包裝在具有固定大小的自定義裝飾器中,並在其不可見時將其子項的可見性設置爲隱藏。這可以防止ApplyTemplate,Measure和Arrange發生在該項目的後代控件上,直到您準備好實現它。
使物理滾動的ScrollIntoView更可靠的一個竅門是調用它兩次:一次立即,一次在DispatcherPriority.ApplicationIdle的調度程序回調中。
決策邏輯滾動滾動條更穩定
如果所有的項目都具有相同的高度,在任何時間視口中可見將保持不變的項目數,造成滾動拇指大小保持不變(因爲如果項目沒有改變,則與總數的比率)。
也可以修改ScrollBar本身的行爲,以便拇指始終計算爲固定大小。要做到這一點,沒有任何哈克後臺代碼:
- 子類跟蹤與自己
- 更改用於邏輯滾動滾動條來使用你的子類的滾動條的模板,以取代在的MeasureOverride拇指位置和大小的計算跟蹤常規one
- 變化,而不是的ScrollViewer模板明確設置您的自定義滾動條的模板上的邏輯滾動滾動條(而不是使用默認的模板)
- 更改列表框模板使用顯式上設置自定義的ScrollViewer模板它創建的ScrollViewer
這意味着複製大量的模板代碼從內置的WPF模板,所以它不是一個非常優雅的解決方案。但是替代方案是使用hacky代碼隱藏來等待所有模板展開,然後找到ScrollBar,並將ScrollBar模板替換爲使用自定義Track的ScrollBar模板。此代碼以一些非常棘手的代碼爲代價保存兩個大型模板(ListBox,ScrollViewer)。
使用不同的面板將是一個更大的工作量:VirtualizingStackPanel是唯一的虛擬化面板,只有它和StackPanel才能進行邏輯滾動。由於您正在利用VirtualizingStackPanel的虛擬化功能,因此您必須重新實現所有這些功能以及所有IScrollInfo信息功能以及常規Panel功能。我可以做這樣的事情,但我會分配幾個,也許很多天來讓它正確。我建議你不要嘗試。
非常感謝。 什麼我可以做,使滾動條的大小在邏輯滾動更穩定?也許使用不同的滾動容器等。 – 2010-06-17 14:49:54
有三種選擇可以改善這種情況:調整項目高度,重新模板ListBox/ScrollViewer/ScrollBar以使用自定義Track控件,或編寫自己的虛擬化面板。我已經將所有這三個細節都添加到了答案中。 – 2010-06-17 15:42:35
廢話..我試圖把你的答案再一次,但是這只是刪除了我的初始UP ..如果你編輯你的答案,我將能夠重新申請:) – 2010-06-17 18:10:47