WPF 列表虛擬化時的滾動方式 WPF 列表開啓虛擬化的方式

ListBox的滾動方式 分爲像素滾動和列表項滾動html

經過ListBox的附加屬性ScrollViewer.CanContentScroll來設置。所以ListBox的默認模板中,含有ScrollViewer,ScrollViewer下存放列表內容緩存

    <ScrollViewer FocusVisualStyle="{x:Null}">
        <ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}"/>
    </ScrollViewer>

 而CanContentScroll,true支持邏輯單元(Item),false支持物理單元(像素)。源碼以下:post

    /// <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);
      }
    }

滾動

一、像素滾動(物理單元) ScrollViewer.CanContentScroll=false性能

經過查看源碼,咱們能夠得知CanContentScroll的默認值爲false。因此列表ListBox/ListView/DataGrid默認像素滾動this

    /// <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;
    }
  }

像素滾動的優勢:平滑--由於按照像素滾動,肉眼分辨較低。url

像素滾動的缺點:耗性能-列表中每一個項,都要計算出寬高具體數值,且滾動時時計算。若是列表中數量過多,就至關卡了。spa

二、列表項滾動(邏輯單元) ScrollViewer.CanContentScroll="True"code

按照Item高寬爲滾動單位。htm

列表項滾動時,列表只會滾動到一個完整的Item,不會有一個Item只顯示一半的狀況。blog

 

虛擬化 

經過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 列表開啓虛擬化的方式

相關文章
相關標籤/搜索