for WPF developers
Home Profile Tips 全記事一覧

ListBox コントロールなどを物理スクロールにする

(2017/05/16 8:03:37 created.)

(2017/05/24 16:59:25 modified.)

ListBox コントロールや DataGrid コントロールはアイテム個々のコンテナを表示していますが、アイテム数が多くてコントロールからはみ出る場合、スクロールバーによってスクロールして表示できるようになっています。このとき、スクロール表示の方法は、既定では論理スクロールといって、アイテムのコンテナ毎の移動量でスクロールする方法になっています。これに対し、ScrollViewer コントロールでの動作に見られるようなピクセル毎の移動量でスクロールする方法を物理スクロールといいます。

言葉で説明されるよりも実際に触って見たほうがわかりやすいので、さっそくサンプルコードを掲載します。

MainViewModel.cs
  1. namespace Tips_PixelScroll.ViewModels
  2. {
  3.     using System.Collections.Generic;
  4.     using System.Linq;
  5.     using Tips_PixelScroll.Models;
  6.  
  7.     public class MainViewModel : NotificationObject
  8.     {
  9.         private IEnumerable<Person> _people;
  10.         /// <summary>
  11.         /// 人物データコレクションを取得します。
  12.         /// </summary>
  13.         public IEnumerable<Person> People
  14.         {
  15.             get
  16.             {
  17.                 if (this._people == null)
  18.                 {
  19.                     this._people = Enumerable.Range(0, 1000)
  20.                                   .Select(i => new Person() { Name = "田中太郎 " + i, Age = i });
  21.                 }
  22.                 return this._people;
  23.             }
  24.         }
  25.     }
  26. }
MainView.xaml
  1. <Window x:Class="Tips_PixelScroll.Views.MainView"
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.         Title="MainView" Height="300" Width="500">
  5.     <Window.Resources>
  6.         <Style TargetType="ListBoxItem">
  7.             <Setter Property="Template">
  8.                 <Setter.Value>
  9.                     <ControlTemplate TargetType="ContentControl">
  10.                         <Border BorderBrush="Black" BorderThickness="1" Margin="2">
  11.                             <StackPanel>
  12.                                 <TextBlock Text="{Binding Name}" />
  13.                                 <TextBlock Text="{Binding Age}" />
  14.                             </StackPanel>
  15.                         </Border>
  16.                     </ControlTemplate>
  17.                 </Setter.Value>
  18.             </Setter>
  19.         </Style>
  20.     </Window.Resources>
  21.  
  22.     <Grid>
  23.         <Grid.RowDefinitions>
  24.             <RowDefinition Height="Auto" />
  25.             <RowDefinition />
  26.         </Grid.RowDefinitions>
  27.         <Grid.ColumnDefinitions>
  28.             <ColumnDefinition />
  29.             <ColumnDefinition />
  30.             <ColumnDefinition />
  31.         </Grid.ColumnDefinitions>
  32.  
  33.         <TextBlock Grid.Row="0" Grid.Column="0" Text="既定の ListBox" />
  34.         <ListBox Grid.Row="1" Grid.Column="0" ItemsSource="{Binding People}" />
  35.  
  36.         <TextBlock Grid.Row="0" Grid.Column="1" Text="仮想化して物理スクロール" />
  37.         <ListBox Grid.Row="1" Grid.Column="1" ItemsSource="{Binding People}"
  38.                  VirtualizingPanel.ScrollUnit="Pixel" />
  39.  
  40.         <TextBlock Grid.Row="0" Grid.Column="2" Text="仮想化なしで物理スクロール" />
  41.         <ListBox Grid.Row="1" Grid.Column="2" ItemsSource="{Binding People}"
  42.                  VirtualizingPanel.ScrollUnit="Pixel"
  43.                  VirtualizingPanel.IsVirtualizing="False" />
  44.     </Grid>
  45. </Window>


論理スクロールでは先頭のアイテムが必ず上からきちんと表示されますが、スクロールさせるとアイテムが動いていないように見えるので、スクロールしているかどうかがわかりにくくなります。これに対して物理スクロールでは、ピクセル単位でのスクロールとなるため、スクロール動作がスムーズに見えます。

どちらがいいかは時と場合によりますが、これらを使い分けられるようにしておくことが大切です。