原文: WPF 清單虛拟化時的滾動方式
ListBox的滾動方式 分為像素滾動和清單項滾動
通過ListBox的附加屬性ScrollViewer.CanContentScroll來設定。是以ListBox的預設模闆中,含有ScrollViewer,ScrollViewer下存放清單内容
<ScrollViewer FocusVisualStyle="{x:Null}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}"/>
</ScrollViewer>
而CanContentScroll,true支援邏輯單元(Item),false支援實體單元(像素)。源碼如下:
/// <summary>
/// 擷取或設定一個值,該值訓示是否支援元素 <see cref="T:System.Windows.Controls.Primitives.IScrollInfo" /> 接口允許滾動。
/// </summary>
/// <returns>
/// <see langword="true" /> 如果 <see cref="T:System.Windows.Controls.ScrollViewer" /> 執行滾動操作使得在邏輯單元; 方面 <see langword="false" /> 如果 <see cref="T:System.Windows.Controls.ScrollViewer" /> 執行滾動操作使得在實體單元方面。
/// 預設值為 <see langword="false" />。
/// </returns>
public bool CanContentScroll
{
get
{
return (bool) this.GetValue(ScrollViewer.CanContentScrollProperty);
}
set
{
this.SetValue(ScrollViewer.CanContentScrollProperty, value);
}
}
滾動
1、像素滾動(實體單元) ScrollViewer.CanContentScroll=false
通過檢視源碼,我們可以得知CanContentScroll的預設值為false。是以清單ListBox/ListView/DataGrid預設像素滾動
/// <summary>
/// 辨別 <see cref="P:System.Windows.Controls.ScrollViewer.CanContentScroll" /> 依賴屬性。
/// </summary>
/// <returns>
/// <see cref="P:System.Windows.Controls.ScrollViewer.CanContentScroll" /> 依賴項屬性的辨別符。
/// </returns>
[CommonDependencyProperty]
public static readonly DependencyProperty CanContentScrollProperty = DependencyProperty.RegisterAttached(nameof (CanContentScroll), typeof (bool), typeof (ScrollViewer), (PropertyMetadata) new FrameworkPropertyMetadata(BooleanBoxes.FalseBox));
[FriendAccessAllowed]
internal static class BooleanBoxes
{
internal static object TrueBox = (object) true;
internal static object FalseBox = (object) false;
internal static object Box(bool value)
{
if (value)
return BooleanBoxes.TrueBox;
return BooleanBoxes.FalseBox;
}
}
像素滾動的優點:平滑--因為按照像素滾動,肉眼分辨較低。
像素滾動的缺點:耗性能-清單中每個項,都要計算出寬高具體數值,且滾動時時計算。如果清單中數量過多,就相當卡了。
2、清單項滾動(邏輯單元) ScrollViewer.CanContentScroll="True"
按照Item高寬為滾動機關。
清單項滾動時,清單隻會滾動到一個完整的Item,不會有一個Item隻顯示一半的情況。
虛拟化
通過VirtualizingPanel,設定清單ListBox/ListView/DataGrid是否開啟虛拟化
VirtualizingPanel其它屬性有:
VirtualizingPanel.ScrollUnit="Pixel"--虛拟化滾動機關(像素/單元)
VirtualizingPanel.IsVirtualizing="True" --是否虛拟
VirtualizingPanel.VirtualizationMode="Recycling"
VirtualizingPanel.CacheLengthUnit="Item" --緩存機關
VirtualizingPanel.CacheLength="20,20"-上下緩存數量
開啟虛拟化:為何需要設定ScrollViewer.CanContentScroll="True"?
開啟虛拟化後,VirtualizingPanel.ScrollUnit會替換原有的ScrollViewer.CanContentScroll滾動方式
虛拟化也有實體單元與邏輯單元之分,滾動單元設定會轉移到VirtualizingPanel.ScrollUnit
但是ScrollViewer.CanContentScroll="False"像素滾動,并不僅僅是滾動消耗性能。當資料很多時加載清單,即使開啟了虛化化,因計算太耗性能,界面一樣卡頓。
有一個解決辦法,設定ScrollViewer.CanContentScroll="True"後,在虛拟化設定中,可以設定虛拟化滾動單元VirtualizingPanel.ScrollUnit="Pixel",此即為虛拟化時的像素滾動。
另:虛拟化時的清單項滾動,VirtualizingPanel.ScrollUnit="Item"清單項
注:
VirtualizingPanel.ScrollUnit和ScrollViewer.CanContentScroll的設定滾動單元一樣。
設定虛拟機關為邏輯單元時,滾動時會自動滾動到一個完整的項,而不是滾動到項的部分。
是以當清單可見區域,Items數量或者高寬會變化時,清單滾動時會閃現。
清單正确開啟虛拟化方式,請看我的另一部落格:
WPF 清單開啟虛拟化的方式