# 機能設計書 9-ListBox

## 概要

本ドキュメントは、Avaloniaフレームワークにおけるリスト選択コントロールである`ListBox`の機能設計を記述する。`SelectingItemsControl`を継承し、単一選択・複数選択、キーボードナビゲーション、スクロール、テキスト検索などの機能を提供する。

### 本機能の処理概要

`ListBox`クラスは、項目のリストを表示し、ユーザーが1つ以上の項目を選択できるコントロールであり、以下の機能を提供する：
- **項目表示**：ItemsSourceまたはItemsによる項目リスト表示
- **単一選択**：1つの項目を選択
- **複数選択**：Ctrl/Shift+クリックによる複数項目選択
- **キーボードナビゲーション**：矢印キーによる移動と選択
- **スクロール**：VirtualizingStackPanelによる仮想化スクロール
- **テキスト検索**：文字入力による項目検索
- **自動スクロール**：選択項目への自動スクロール

**業務上の目的・背景**：設定画面、ファイル選択、オプション選択など、複数の選択肢から選ぶUIパターンに使用される基本的なリストコントロール。

**機能の利用シーン**：
- 設定画面のオプションリスト
- ファイル/フォルダ選択
- メッセージ一覧
- データ一覧と選択

**主要な処理内容**：
1. `Items`/`ItemsSource`による項目管理
2. `Selection`/`SelectedItem`/`SelectedIndex`による選択管理
3. `SelectionMode`による選択モード制御
4. `ListBoxItem`コンテナによる項目表示
5. `VirtualizingStackPanel`による仮想化
6. キーボード/マウスによる選択操作

**関連システム・外部連携**：
- `SelectingItemsControl`：選択機能基盤
- `ItemsControl`：項目管理基盤
- `ISelectionModel`：選択状態管理
- `VirtualizingStackPanel`：仮想化パネル
- `IScrollable`：スクロール機能

**権限による制御**：特になし

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| S-01 | SettingsWindow | 表示/入力 | 設定オプション選択 |

## 機能種別

UIコントロール / リスト表示 / 選択

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Items | IEnumerable | No | 表示する項目コレクション | ItemsControl継承 |
| ItemsSource | IEnumerable? | No | データソース | ItemsControl継承 |
| SelectedIndex | int | No | 選択インデックス | TwoWayバインディング、デフォルト: -1 |
| SelectedItem | object? | No | 選択項目 | TwoWayバインディング |
| SelectedItems | IList? | No | 選択項目リスト（複数選択時） | - |
| Selection | ISelectionModel | No | 選択モデル | - |
| SelectionMode | SelectionMode | No | 選択モード | Single/Multiple/Toggle/AlwaysSelected |
| AutoScrollToSelectedItem | bool | No | 選択項目への自動スクロール | デフォルト: true |
| IsTextSearchEnabled | bool | No | テキスト検索有効 | デフォルト: false |
| WrapSelection | bool | No | 選択の循環 | デフォルト: false |
| SelectedValue | object? | No | 選択値 | TwoWayバインディング |
| SelectedValueBinding | BindingBase? | No | 選択値バインディング | - |

### 入力データソース

- ItemsSource/Itemsプロパティ
- マウスクリック
- キーボード入力（矢印キー、Enter、Space）
- テキスト入力（IsTextSearchEnabled時）
- データバインディング

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| SelectionChanged | event | 選択変更時イベント |
| SelectedIndex | int | 現在の選択インデックス |
| SelectedItem | object? | 現在の選択項目 |
| SelectedItems | IList? | 現在の選択項目リスト |
| Scroll | IScrollable? | スクロール情報 |

### 出力先

- SelectionChangedイベントリスナー
- バインディングターゲット
- 選択状態のコンテナ（:selected擬似クラス）

## 処理フロー

### 処理シーケンス

```
1. 項目クリック
   └─ OnPointerPressed（ListBoxItem）
   └─ UpdateSelectionFromEvent
   └─ Selection.Select/Deselect
   └─ MarkContainerSelected
   └─ SelectionChangedイベント発火

2. キーボードナビゲーション
   └─ OnKeyDown
   └─ MoveSelection
   └─ GetNextControl（INavigableContainer）
   └─ UpdateSelection
   └─ Focus

3. 複数選択（Shift+クリック）
   └─ UpdateSelection（rangeModifier: true）
   └─ Selection.SelectRange
   └─ コンテナ状態更新

4. テキスト検索
   └─ OnTextInput
   └─ GetIndexFromTextSearch
   └─ SelectedIndex設定

5. 選択項目自動スクロール
   └─ AutoScrollToSelectedItemIfNecessary
   └─ ScrollIntoView
```

### フローチャート

```mermaid
flowchart TD
    A[ユーザー入力] --> B{入力種別?}
    B -->|マウスクリック| C[UpdateSelectionFromEvent]
    B -->|矢印キー| D[OnKeyDown]
    B -->|テキスト入力| E[OnTextInput]

    C --> F{SelectionMode?}
    D --> G[MoveSelection]
    E --> H[GetIndexFromTextSearch]

    F -->|Single| I[Selection.Clear + Select]
    F -->|Multiple+Shift| J[Selection.SelectRange]
    F -->|Multiple+Ctrl| K[Selection.Select/Deselect]
    F -->|Toggle| L[Toggle Selection]

    G --> M[GetNextControl]
    M --> N[UpdateSelection]
    N --> O[Focus]

    H --> P[SelectedIndex設定]

    I --> Q[MarkContainerSelected]
    J --> Q
    K --> Q
    L --> Q

    Q --> R[SelectionChangedイベント]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | ItemsPanelデフォルト | VirtualizingStackPanelを使用 | 静的コンストラクタ |
| BR-02 | TabNavigationMode | KeyboardNavigationMode.Onceを使用 | 静的コンストラクタ |
| BR-03 | SelectionMode.Single | 1つの項目のみ選択可能 | SelectionMode.Single |
| BR-04 | SelectionMode.Multiple | 複数項目選択可能 | SelectionMode.Multiple |
| BR-05 | SelectionMode.Toggle | クリックで選択/解除切り替え | SelectionMode.Toggle |
| BR-06 | SelectionMode.AlwaysSelected | 常に1つ以上選択状態を維持 | SelectionMode.AlwaysSelected |
| BR-07 | Shift+矢印 | 範囲選択 | Multiple + Shift |
| BR-08 | Ctrl+A | 全選択 | Multiple + Ctrl+A |
| BR-09 | IsSelectedChangedEvent | コンテナからの選択変更通知をバブルで処理 | RoutingStrategies.Bubble |
| BR-10 | AutoScrollToSelectedItem | 選択項目が見えるよう自動スクロール | AutoScrollToSelectedItem == true |

### 計算ロジック

**SelectAll**：
```csharp
public void SelectAll() => Selection.SelectAll();
```

**UnselectAll**：
```csharp
public void UnselectAll() => Selection.Clear();
```

## データベース操作仕様

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | InvalidOperationException | SelectionとSelectedItemsの同時設定 | 例外スロー |
| - | ArgumentException | SelectionのSourceがItemsと異なる | 例外スロー |

### リトライ仕様

該当なし

## トランザクション仕様

該当なし

## パフォーマンス要件

- VirtualizingStackPanelによるUI仮想化
- 大量項目でも効率的なスクロール
- SelectionModel.BatchUpdateによる効率的な複数選択
- コンテナリサイクル（ListBoxItem）

## セキュリティ考慮事項

- 入力データの検証はアプリケーション側で実施
- IsSelectedプロパティの変更通知は適切にハンドル

## 備考

- WPFのListBoxと高い互換性
- SelectingItemsControlから継承した選択機能
- PART_ScrollViewerテンプレートパーツ

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: クラス定義とプロパティを理解する

ListBoxの基本構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ListBox.cs | `src/Avalonia.Controls/ListBox.cs` | 19-20行目：クラス定義、TemplatePart |
| 1-2 | ListBox.cs | `src/Avalonia.Controls/ListBox.cs` | 25-26行目：DefaultPanel（VirtualizingStackPanel） |
| 1-3 | ListBox.cs | `src/Avalonia.Controls/ListBox.cs` | 31-56行目：プロパティ定義（Scroll, SelectedItems, Selection, SelectionMode） |
| 1-4 | ListBox.cs | `src/Avalonia.Controls/ListBox.cs` | 63-69行目：静的コンストラクタ |

**読解のコツ**:
- `SelectingItemsControl`を継承
- 親クラスのprotectedプロパティをpublicに公開
- デフォルトでVirtualizingStackPanelを使用

#### Step 2: 選択機能を理解する（SelectingItemsControl）

選択処理の基盤を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SelectingItemsControl.cs | `src/Avalonia.Controls/Primitives/SelectingItemsControl.cs` | 42-56行目：SelectedIndexProperty（TwoWay、デフォルト-1） |
| 2-2 | SelectingItemsControl.cs | `src/Avalonia.Controls/Primitives/SelectingItemsControl.cs` | 61-66行目：SelectedItemProperty（TwoWay） |
| 2-3 | SelectingItemsControl.cs | `src/Avalonia.Controls/Primitives/SelectingItemsControl.cs` | 93-104行目：SelectionProperty、SelectionModeProperty |
| 2-4 | SelectingItemsControl.cs | `src/Avalonia.Controls/Primitives/SelectingItemsControl.cs` | 132-135行目：SelectionChangedEvent |

**主要処理フロー**:
- **42-56行目**: SelectedIndexはTwoWayバインディング
- **109-112行目**: IsSelectedは添付プロパティ

#### Step 3: 選択更新処理を理解する

UpdateSelection系メソッドを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SelectingItemsControl.cs | `src/Avalonia.Controls/Primitives/SelectingItemsControl.cs` | 747-809行目：UpdateSelectionメソッド |
| 3-2 | SelectingItemsControl.cs | `src/Avalonia.Controls/Primitives/SelectingItemsControl.cs` | 882-912行目：UpdateSelectionFromEventメソッド |
| 3-3 | SelectingItemsControl.cs | `src/Avalonia.Controls/Primitives/SelectingItemsControl.cs` | 989-1026行目：OnSelectionModelSelectionChanged |

**主要処理フロー**:
- **747-809行目**: SelectionMode、rangeModifier、toggleModifierに基づく選択処理
- **882-912行目**: イベントからの選択更新（PointerEvent、KeyEvent、GotFocusEvent）
- **989-1026行目**: SelectionModel変更時のコンテナ更新とイベント発火

#### Step 4: キーボードナビゲーションを理解する

OnKeyDownとMoveSelectionを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ListBox.cs | `src/Avalonia.Controls/ListBox.cs` | 129-151行目：OnKeyDown |
| 4-2 | SelectingItemsControl.cs | `src/Avalonia.Controls/Primitives/SelectingItemsControl.cs` | 684-736行目：MoveSelectionメソッド |

**主要処理フロー**:
- **129-151行目**: 矢印キーでMoveSelection、Ctrl+AでSelectAll
- **684-736行目**: INavigableContainerからGetNextControlで次のコントロールを取得

#### Step 5: コンテナ管理を理解する

ListBoxItemの作成と準備を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | ListBox.cs | `src/Avalonia.Controls/ListBox.cs` | 119-127行目：CreateContainerForItemOverride、NeedsContainerOverride |
| 5-2 | SelectingItemsControl.cs | `src/Avalonia.Controls/Primitives/SelectingItemsControl.cs` | 503-537行目：PrepareContainerForItemOverride、ContainerForItemPreparedOverride |
| 5-3 | SelectingItemsControl.cs | `src/Avalonia.Controls/Primitives/SelectingItemsControl.cs` | 1194-1206行目：MarkContainerSelected |

**主要処理フロー**:
- **119-122行目**: ListBoxItemコンテナを作成
- **503-537行目**: コンテナ準備時にIsSelected状態を同期
- **1194-1206行目**: コンテナのIsSelectedプロパティを更新

### プログラム呼び出し階層図

```
ListBox
    │
    ├─ SelectingItemsControl（選択機能）
    │      ├─ ISelectionModel
    │      │      ├─ Select/Deselect
    │      │      ├─ SelectRange
    │      │      └─ SelectAll/Clear
    │      ├─ SelectedIndex/SelectedItem
    │      ├─ SelectionMode
    │      └─ SelectionChangedEvent
    │
    ├─ ItemsControl（項目管理）
    │      ├─ Items/ItemsSource
    │      ├─ ItemsPresenter
    │      └─ ItemContainerGenerator
    │
    ├─ ListBoxItem（コンテナ）
    │      └─ IsSelected
    │
    └─ VirtualizingStackPanel（仮想化パネル）
           └─ IScrollable
```

### データフロー図

```
[入力]                     [処理]                          [出力]

ItemsSource設定
        │
        ▼
   ItemsControl ──────────▶ コンテナ生成
        │                       │
        ▼                       ▼
   ListBoxItem作成 ────────▶ PrepareContainer
        │                       │
        ▼                       ▼
マウス/キーボード入力            IsSelected同期
        │                       │
        ▼                       ▼
   UpdateSelection ─────────▶ Selection.Select
        │                       │
        ▼                       ▼
   MarkContainerSelected ───▶ SelectionChangedイベント
                                │
                                ▼
                           バインディング更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ListBox.cs | `src/Avalonia.Controls/ListBox.cs` | ソース | ListBoxコントロール |
| SelectingItemsControl.cs | `src/Avalonia.Controls/Primitives/SelectingItemsControl.cs` | ソース | 選択機能基盤 |
| ItemsControl.cs | `src/Avalonia.Controls/ItemsControl.cs` | ソース | 項目管理基盤 |
| ListBoxItem.cs | `src/Avalonia.Controls/ListBoxItem.cs` | ソース | 項目コンテナ |
| ISelectionModel.cs | `src/Avalonia.Controls/Selection/ISelectionModel.cs` | ソース | 選択モデルIF |
| InternalSelectionModel.cs | `src/Avalonia.Controls/Selection/InternalSelectionModel.cs` | ソース | 内部選択モデル |
| VirtualizingStackPanel.cs | `src/Avalonia.Controls/VirtualizingStackPanel.cs` | ソース | 仮想化パネル |
| SelectionMode.cs | `src/Avalonia.Controls/Selection/SelectionMode.cs` | ソース | 選択モード列挙型 |
| SelectionChangedEventArgs.cs | `src/Avalonia.Controls/SelectionChangedEventArgs.cs` | ソース | 選択変更イベント引数 |
