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

ListBox List

ListBox はスクロール可能なリストからアイテムを選択できるコントロールです。単一・複数・拡張選択モードをサポートし、データコレクションへのバインドが可能です。

概要

WPF の ListBoxSelector を継承したリストコントロールです。ItemsSource にコレクションをバインドすることで、動的なアイテムリストを表示できます。ItemTemplate でアイテムの表示方法をカスタマイズできます。

SelectionMode プロパティで選択の挙動を制御します。Single は一度に 1 つだけ選択、Multiple は Ctrl キーなしでクリックするたびに選択を切り替え、Extended は Shift+クリックで範囲選択・Ctrl+クリックで個別追加選択が可能です。

SelectedItems(複数選択モード)や SelectedItem(単一選択モード)を ViewModel にバインドすることで、選択されたアイテムを取得できます。複数選択のバインドは直接は難しいため、IsSelected を各アイテムの ViewModel プロパティにバインドするか、ビヘイビアを使うのが一般的です。

大量のアイテムを表示する場合、デフォルトで VirtualizingStackPanel がアイテムホストとして使用されるため、表示領域外のアイテムは仮想化されてメモリを節約できます。

画面キャプチャ

listbox demo screen

デモしているプロパティ

以下のプロパティが WPF 標準コントロールデモアプリでインタラクティブにデモされています。

プロパティ設定値説明
SelectionModeSingle / Multiple / Extended選択モードを設定します。ファイルマネージャーやメールクライアントのような一括操作が必要な場面では Extended、タグやカテゴリを複数チェックするような場面では Multiple を使います。Extended を使うと Shift/Ctrl+クリックで範囲・個別選択ができ、SelectedItems に選択中のすべてのアイテムが格納されます。Multiple はクリックするたびに Ctrl キーなしで選択状態をトグルできます。ただし Windows Explorer の操作に慣れたユーザーには Extended の方が直感的で、Multiple は「クリックするたびに選択が変わる」挙動がわかりにくいという落とし穴があります。
DisplayMemberPath (ItemsControl)string各アイテムオブジェクトの表示テキストとして使うプロパティ名を指定します。アイコンや複数行など複雑なレイアウトが不要で単純なテキストリストで十分な場合に使い、複雑な表示には ItemTemplate を使います。WPF は内部的に指定したプロパティパスにバインドした TextBlock を自動生成して表示します。注意点として、DisplayMemberPath と ItemTemplate は同時に設定できず、両方を指定するとランタイム例外が発生します。
SelectedIndex (Selector)int選択されているアイテムのゼロ始まりインデックスを取得・設定します。初期選択の設定やキー操作によるナビゲーションをプログラムで制御する際に使います。値を設定すると SelectionChanged イベントが発火し、SelectedItem も連動して更新されます。範囲外のインデックスを設定しても例外は発生せず無視されます。-1 を設定すると明示的に選択をクリアできます。
SelectedItem (Selector)object選択されているアイテムオブジェクトを取得・設定します。MVVM パターンでは ViewModel のプロパティに Mode=TwoWay でバインドして選択状態を双方向同期するのが基本パターンで、ViewModel 側から選択を変更したいとき(ナビゲーションや初期化時など)に Setter が有効です。参照の一致でアイテムを照合するため、ViewModel が ItemsSource のオブジェクトと同一インスタンスではなく新しいオブジェクトを生成すると、同じデータ内容でも SelectedItem バインドが一致しないという落とし穴があります。
SelectedValuePath / SelectedValue (Selector)string / objectSelectedValuePath で指定したプロパティの値を SelectedValue として取得・設定します。例えば SelectedValuePath="Id" として SelectedValue に整数 ID をバインドすることで、オブジェクト全体ではなく ID だけで選択を管理できる ID ベースの選択パターンに使います。このパターンを使うと、SelectedValue が変わると内部で一致する ItemsSource のアイテムが選択されます。ただし SelectedValue は ItemsSource が設定された後でないと有効に機能せず、ItemsSource の設定前に SelectedValue を設定すると選択が失われることがあります。
IsSelected (ListBoxItem)bool個々のリストアイテムが選択されているかどうかを示します。ItemContainerStyle に Setter を定義して ViewModel の対応するプロパティに TwoWay バインドすることで、選択状態を ViewModel で直接管理できます。バインドが有効な場合、ViewModel のプロパティを True にするとそのアイテムが選択状態になります。落とし穴として、バインドの DataContext は各アイテムの ViewModel を指す必要があり、DataContext が意図しないオブジェクトを指している場合はバインドがサイレントに失敗します。

XAML 使用例

<ListBox ItemsSource="{Binding Countries}"
         DisplayMemberPath="Name"
         SelectedItem="{Binding SelectedCountry, Mode=TwoWay}"
         SelectionMode="Extended"
         ScrollViewer.HorizontalScrollBarVisibility="Disabled">
</ListBox>

<!-- カスタム ItemTemplate -->
<ListBox ItemsSource="{Binding Files}"
         SelectionMode="Single"
         SelectedItem="{Binding SelectedFile, Mode=TwoWay}">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <StackPanel Orientation="Horizontal">
        <Image Source="{Binding Icon}" Width="16" Height="16" />
        <TextBlock Text="{Binding Name}" Margin="8,0,0,0" />
      </StackPanel>
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

主な使用例

ヒントとベストプラクティス

関連コントロール

ソースコード

このデモ画面のソースコードは GitHub で公開しています。

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