WPF 標準コントロールデモアプリ › ScrollViewer

ScrollViewer Layout

ScrollViewer は、自分より大きい内容の一部を表示し、残りをスクロールして見せるコンテナーです。ListBox、TextBox、TreeView、DataGrid も、それぞれ内部に 1 つ持っています。

スクロールバーの 4 つの設定を、収まる内容とはみ出す内容で比べる

VerticalScrollBarVisibility と HorizontalScrollBarVisibility は、バーを表示するかと、内容をスクロールできるかを決めます。デモアプリと同じく、幅 200、高さ 100 の ScrollViewer に、収まる 2 つのラベルと、はみ出す 9 つのラベルを入れて比べました。

バーが実際に表示されているかを表す ComputedVerticalScrollBarVisibility が Visible だったのは、Auto でラベルが 9 つのときと Visible のときだけで、それ以外はすべて Collapsed でした。計測したのは縦のバーです。HorizontalScrollBarVisibility にも同じ 4 つの値を設定できますが、横方向は計測していません。

VerticalScrollBarVisibility 項目数 Computed... ViewportWidth ExtentHeight 50 までスクロールした後の位置
Disabled 2 Collapsed 200 55.92 0
Disabled 9 Collapsed 200 100 0
Auto 2 Collapsed 200 55.92 0
Auto 9 Visible 183 251.64 50
Hidden 2 Collapsed 200 55.92 0
Hidden 9 Collapsed 200 251.64 50
Visible 2 Visible 183 55.92 0
Visible 9 Visible 183 251.64 50

内容が収まる場合とはみ出す場合の、VerticalScrollBarVisibility の各値。.NET 10 / Windows 11 で計測。

既定値と、コントロールの中の ScrollViewer の変え方

ScrollViewer の既定値は、VerticalScrollBarVisibility が Visible、HorizontalScrollBarVisibility が Disabled です。内部に持つコントロールは、それぞれ独自の値を設定しています。ListBox、TreeView、DataGrid の中の ScrollViewer は横方向が Auto、TextBox の中のものは Hidden でした。

コントロールの中の ScrollViewer を変えるには、コントロール自身に添付プロパティを設定します。ListBox に ScrollViewer.HorizontalScrollBarVisibility="Disabled" を設定すると、中の ScrollViewer に届きました。Disabled にした別の ScrollViewer で ListBox を包んでも届かず、中のものは Auto のままでした。

CanContentScroll:ピクセルか項目か、そして仮想化

CanContentScroll は、内容が自分の単位でスクロールするかどうかを決めます。デモアプリの 9 つのラベルの StackPanel では、False で ExtentHeight 251.64、ViewportHeight 100 とピクセル単位になり、LineDown 1 回で 16 動きました。True では 9 と 3 と項目の数になり、LineDown 1 回で 1 項目動きました。

一覧では仮想化にも関わります。既定の設定の、1000 項目、高さ 200 の ListBox は、True で 10 個、False で 1000 個すべての ListBoxItem を作りました。False にすると仮想化は止まりますが、True だけで仮想化されるわけではなく、ListBox の既定のように項目が VirtualizingStackPanel に並び、VirtualizingPanel.IsVirtualizing が True のままである必要があります。長い一覧では True のままにします。

遅延スクロールと、大きさが分かる時点

IsDeferredScrollingEnabled は、つまみを離すまで内容の移動を待つかどうかです。False では、つまみを 30 下へドラッグすると、ドラッグ中に VerticalOffset と ContentVerticalOffset がどちらも 114.38 になりました。True ではドラッグ中はどちらも 0 のままで、離した時点で 114.38 になりました。ドラッグは、実際のマウスではなく、つまみのドラッグのイベント(開始、30 の移動、完了)を送って再現しました。

大きさのプロパティは、レイアウトの後でないと分かりません。ExtentHeight と ViewportHeight は、最初のレイアウトの前は 0、後は 251.64 と 100 でした。StackPanel の中などで ScrollViewer がまったくスクロールしない理由は、下にリンクした記事で扱っています。

条件 計測値
既定値: VerticalScrollBarVisibility / HorizontalScrollBarVisibility Visible / Disabled
デモの項目、CanContentScroll=False: 大きさ / LineDown の後の位置 内容 251.64、表示 100 / 16
デモの項目、CanContentScroll=True: 大きさ / LineDown の後の位置 内容 9、表示 3 / 1
ListBox、1000 項目、CanContentScroll=True: 作られた項目の数 10
ListBox、1000 項目、CanContentScroll=False: 作られた項目の数 1000
IsDeferredScrollingEnabled=False: 位置 / 内容の位置、ドラッグ中、離した後 114.38 / 114.38、114.38 / 114.38
IsDeferredScrollingEnabled=True: 位置 / 内容の位置、ドラッグ中、離した後 0 / 0、114.38 / 114.38
ListBox / TextBox / TreeView / DataGrid の中の HorizontalScrollBarVisibility Auto / Hidden / Auto / Auto
ListBox の中: 添付プロパティで Disabled / 外側の ScrollViewer を Disabled Disabled / Auto
レイアウト前の ExtentHeight / ViewportHeight、レイアウト後 0 / 0、251.64 / 100

CanContentScroll、遅延スクロール、コントロールの中の ScrollViewer。.NET 10 / Windows 11 で計測。

デモアプリで試す

デモアプリの ScrollViewer のページ。左にコントロールの一覧、右に最初の節の CanContentScroll

デモアプリの ScrollViewer のページには、CanContentScroll、IsDeferredScrollingEnabled、縦横のスクロールバーの設定、縦横の大きさと位置を表す読み取り専用のプロパティの欄があります。読み取り専用の値は、ラベルが 2 つと 9 つの場合と、ラベルを横に並べた場合について表示します。どの欄も、枠付きのラベルを入れた高さ 100 の ScrollViewer を使っています。各欄の下の「Show Code」リンクで、その欄の XAML を表示できます。次の XAML は、CanContentScroll の欄(ScrollViewerUsageControl.xaml)から、スタイルと周囲の GroupBox を省き、名前空間の宣言を加えたものです。スタイルは、ScrollViewer の Height を 100 にし、各ラベルに幅 1 の黒い枠を付けています。

<StackPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <CheckBox x:Name="CanContentScrollCheckBox" Content="CanContentScroll" />

  <ScrollViewer x:Name="CanContentScrollScrollViewer"
                CanContentScroll="{Binding IsChecked, ElementName=CanContentScrollCheckBox}"
                Height="100">
    <StackPanel Orientation="Vertical">
      <Label Content="Item1" />
      <Label Content="Item2" />
      <Label Content="Item3" />
      <Label Content="Item4" />
      <Label Content="Item5" />
      <Label Content="Item6" />
      <Label Content="Item7" />
      <Label Content="Item8" />
      <Label Content="Item9" />
    </StackPanel>
  </ScrollViewer>
</StackPanel>

関連するコントロールと記事

ソースコードと計測の方法

このページの挙動の記述は、すべて .NET 10 / Windows 11 で実際に動かして確かめたものです。計測には、このサイトのスクリーンショット生成ツールの ScrollViewerDemoScene を使いました。内容はデモアプリと同じ枠付きのラベルです。つまみのドラッグは、マウスでドラッグしたときと同じ DragStarted・DragDelta・DragCompleted のイベントをつまみに発生させて再現しました。大きさは、計測したマシンでの値です。

GitHub で ScrollViewer のソースコードを見る →