# 機能設計書 10-ComboBox

## 概要

本ドキュメントは、Avaloniaフレームワークにおけるドロップダウンリストコントロールである`ComboBox`の機能設計を記述する。`SelectingItemsControl`を継承し、ドロップダウン表示、単一選択、編集可能モード、テキスト検索などの機能を提供する。

### 本機能の処理概要

`ComboBox`クラスは、ドロップダウンリストから項目を選択するコントロールであり、以下の機能を提供する：
- **ドロップダウン表示**：Popupによる項目リスト表示
- **単一選択**：リストから1つの項目を選択
- **編集可能モード**：テキスト入力による項目検索・選択
- **キーボードナビゲーション**：矢印キーによる項目移動
- **テキスト検索**：入力文字による項目フィルタリング
- **プレースホルダー**：未選択時のプレースホルダーテキスト
- **SelectionBoxItem**：選択項目の表示コンテンツ

**業務上の目的・背景**：設定画面、フォーム入力、フィルタ選択など、限定された選択肢から1つを選ぶUIパターンに使用される基本的なドロップダウンコントロール。

**機能の利用シーン**：
- 国/地域選択
- カテゴリ選択
- 並び替え条件選択
- 設定オプション選択

**主要な処理内容**：
1. `IsDropDownOpen`によるポップアップ開閉制御
2. `SelectedItem`/`SelectedIndex`による選択管理
3. `IsEditable`による編集モード切り替え
4. `Text`プロパティによるテキスト入力
5. `SelectionBoxItem`による選択表示
6. `ComboBoxItem`コンテナによる項目表示

**関連システム・外部連携**：
- `SelectingItemsControl`：選択機能基盤
- `Popup`：ドロップダウン表示
- `TextBox`：編集可能モードの入力
- `VirtualizingStackPanel`：仮想化パネル
- `TextSearch`：テキスト検索

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

## 関連画面

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

## 機能種別

UIコントロール / ドロップダウン選択

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Items | IEnumerable | No | 表示する項目コレクション | ItemsControl継承 |
| ItemsSource | IEnumerable? | No | データソース | ItemsControl継承 |
| SelectedIndex | int | No | 選択インデックス | TwoWayバインディング、デフォルト: -1 |
| SelectedItem | object? | No | 選択項目 | TwoWayバインディング |
| IsDropDownOpen | bool | No | ドロップダウン開閉状態 | デフォルト: false |
| IsEditable | bool | No | 編集可能モード | デフォルト: false |
| MaxDropDownHeight | double | No | ドロップダウン最大高さ | デフォルト: 200 |
| PlaceholderText | string? | No | プレースホルダーテキスト | - |
| PlaceholderForeground | IBrush? | No | プレースホルダー前景色 | - |
| Text | string? | No | 編集テキスト | TwoWayバインディング（IsEditable時） |
| SelectionBoxItemTemplate | IDataTemplate? | No | 選択表示テンプレート | TwoWayバインディング |
| HorizontalContentAlignment | HorizontalAlignment | No | 水平コンテンツ配置 | - |
| VerticalContentAlignment | VerticalAlignment | No | 垂直コンテンツ配置 | - |

### 入力データソース

- ItemsSource/Itemsプロパティ
- マウスクリック（ドロップダウン開閉・項目選択）
- キーボード入力（F4、Alt+Up/Down、矢印キー、Enter、Space、Escape）
- テキスト入力（IsEditable時）
- マウスホイール

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| SelectionChanged | event | 選択変更時イベント |
| DropDownOpened | event | ドロップダウン開時イベント |
| DropDownClosed | event | ドロップダウン閉時イベント |
| SelectedIndex | int | 現在の選択インデックス |
| SelectedItem | object? | 現在の選択項目 |
| SelectionBoxItem | object? | 選択表示コンテンツ |
| Text | string? | 現在のテキスト（IsEditable時） |

### 出力先

- SelectionChanged/DropDownOpened/DropDownClosedイベントリスナー
- バインディングターゲット
- Popupによるドロップダウン表示

## 処理フロー

### 処理シーケンス

```
1. ドロップダウン開閉
   ├─ ポインタークリック → OnPointerPressed/Released
   ├─ F4キー → OnKeyDown
   ├─ Alt+Up/Down → OnKeyDown
   └─ Enter/Space（非編集時） → OnKeyDown
   └─ IsDropDownOpen設定
   └─ PopupOpened/Closed
   └─ DropDownOpened/Closedイベント

2. 項目選択
   └─ ポインターリリース（Popup内）
   └─ UpdateSelectionFromEvent
   └─ Popup.Close
   └─ UpdateSelectionBoxItem
   └─ SelectionChangedイベント

3. キーボードナビゲーション（Popup閉時）
   └─ OnKeyDown
   └─ Up/Down → SelectPrevious/SelectNext
   └─ MoveSelection
   └─ SelectedIndex更新

4. テキスト入力（IsEditable時）
   └─ TextChanged
   └─ Items検索
   └─ SelectedIndex/SelectedItem設定
```

### フローチャート

```mermaid
flowchart TD
    A[ユーザー入力] --> B{入力種別?}
    B -->|クリック| C[OnPointerPressed/Released]
    B -->|F4/Alt+矢印| D[OnKeyDown]
    B -->|テキスト入力| E[TextChanged]
    B -->|マウスホイール| F[OnPointerWheelChanged]

    C --> G{ドロップダウン状態?}
    G -->|閉| H[IsDropDownOpen = true]
    G -->|開| I[IsDropDownOpen = false]

    D --> J{キー種別?}
    J -->|F4/Alt+矢印| K[Toggle IsDropDownOpen]
    J -->|Escape| L[Close DropDown]
    J -->|Enter/Space| M[Open DropDown]
    J -->|Up/Down| N[SelectPrevious/Next]

    E --> O[Items検索]
    O --> P{一致項目あり?}
    P -->|Yes| Q[SelectedItem設定]
    P -->|No| R[SelectedItem = null]

    H --> S[PopupOpened]
    S --> T[TryFocusSelectedItem]
    T --> U[DropDownOpenedイベント]

    I --> V[PopupClosed]
    V --> W[DropDownClosedイベント]

    N --> X[MoveSelection]
    X --> Y[SelectedIndex更新]
    Y --> Z[UpdateSelectionBoxItem]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | ItemsPanelデフォルト | VirtualizingStackPanelを使用 | 静的コンストラクタ |
| BR-02 | Focusableデフォルト | Focusable = trueを設定 | 静的コンストラクタ |
| BR-03 | IsTextSearchEnabled | テキスト検索をデフォルトで有効 | 静的コンストラクタ |
| BR-04 | F4でトグル | F4キーでドロップダウン開閉 | Alt修飾なし |
| BR-05 | Alt+Up/Downでトグル | Alt+矢印キーでドロップダウン開閉 | Alt修飾あり |
| BR-06 | Escapeで閉じる | Escapeキーでドロップダウン閉じる | IsDropDownOpen時 |
| BR-07 | Enter/Spaceで開く | Enter/Spaceでドロップダウン開く | 非編集モードかつ閉時 |
| BR-08 | 選択でPopup閉じる | 項目選択時にPopupを閉じる | UpdateSelectionFromEvent |
| BR-09 | :dropdownopen擬似クラス | ドロップダウン開時に適用 | IsDropDownOpen == true |
| BR-10 | :pressed擬似クラス | ポインター押下時に適用 | OnPointerPressed |
| BR-11 | SelectionBoxItemTemplateデフォルト | ItemTemplateにフォールバック | CoerceSelectionBoxItemTemplate |

### 計算ロジック

**SelectNext/SelectPrevious**：
```csharp
private bool SelectNext() => MoveSelection(SelectedIndex, 1, WrapSelection);
private bool SelectPrevious() => MoveSelection(SelectedIndex, -1, WrapSelection);
```

**TextChanged（IsEditable時）**：
```csharp
foreach (object? item in Items) {
    string itemText = GetItemTextValue(item);
    if (string.Equals(newValue, itemText, StringComparison.CurrentCultureIgnoreCase)) {
        selectedIdx = i;
        selectedItem = item;
        break;
    }
}
```

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | - | PART_Popupが見つからない | OnApplyTemplateで必須として処理 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- VirtualizingStackPanelによるUI仮想化
- 大量項目でも効率的なスクロール
- ポップアップ開閉の即座な応答
- テキスト検索のリアルタイム応答

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

- 入力テキストのサニタイズなし（アプリ側で対応）
- オートメーション対応（ComboBoxAutomationPeer）

## 備考

- WPFのComboBoxと高い互換性
- PART_Popup（必須）、PART_EditableTextBox（オプション）テンプレートパーツ
- SelectingItemsControlから継承した選択機能

---

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

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

### 推奨読解順序

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ComboBox.cs | `src/Avalonia.Controls/ComboBox.cs` | 23-29行目：クラス定義、TemplatePart、PseudoClasses |
| 1-2 | ComboBox.cs | `src/Avalonia.Controls/ComboBox.cs` | 34-35行目：DefaultPanel（VirtualizingStackPanel） |
| 1-3 | ComboBox.cs | `src/Avalonia.Controls/ComboBox.cs` | 40-96行目：プロパティ定義 |
| 1-4 | ComboBox.cs | `src/Avalonia.Controls/ComboBox.cs` | 119-124行目：静的コンストラクタ |

**読解のコツ**:
- `SelectingItemsControl`を継承
- PART_Popup（必須）、PART_EditableTextBox（オプション）
- :dropdownopen、:pressed擬似クラス

#### Step 2: ドロップダウン制御を理解する

Popup開閉の処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ComboBox.cs | `src/Avalonia.Controls/ComboBox.cs` | 251-301行目：OnKeyDown |
| 2-2 | ComboBox.cs | `src/Avalonia.Controls/ComboBox.cs` | 325-348行目：OnPointerPressed |
| 2-3 | ComboBox.cs | `src/Avalonia.Controls/ComboBox.cs` | 351-373行目：OnPointerReleased |
| 2-4 | ComboBox.cs | `src/Avalonia.Controls/ComboBox.cs` | 392-405行目：OnApplyTemplate（Popup取得） |

**主要処理フロー**:
- **258-263行目**: F4、Alt+Up/Downでトグル
- **264-268行目**: Escapeでクローズ
- **269-273行目**: Enter/Spaceでオープン（非編集モード）
- **392-405行目**: PART_Popup、PART_EditableTextBox取得

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

項目選択の処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ComboBox.cs | `src/Avalonia.Controls/ComboBox.cs` | 375-384行目：UpdateSelectionFromEvent |
| 3-2 | ComboBox.cs | `src/Avalonia.Controls/ComboBox.cs` | 386-389行目：ShouldTriggerSelection |
| 3-3 | ComboBox.cs | `src/Avalonia.Controls/ComboBox.cs` | 535-586行目：UpdateSelectionBoxItem |
| 3-4 | ComboBox.cs | `src/Avalonia.Controls/ComboBox.cs` | 608-645行目：MoveSelection |

**主要処理フロー**:
- **375-384行目**: 選択時にPopup.Close
- **535-586行目**: 選択項目からSelectionBoxItem生成（VisualBrush使用）
- **608-645行目**: 上下キーでの項目移動

#### Step 4: 編集可能モードを理解する

IsEditable時の処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ComboBox.cs | `src/Avalonia.Controls/ComboBox.cs` | 456-465行目：OnGotFocus |
| 4-2 | ComboBox.cs | `src/Avalonia.Controls/ComboBox.cs` | 600-606行目：UpdateInputTextFromSelection |
| 4-3 | ComboBox.cs | `src/Avalonia.Controls/ComboBox.cs` | 685-720行目：TextChanged |

**主要処理フロー**:
- **456-465行目**: フォーカス時にTextBoxにフォーカス移動
- **685-720行目**: テキスト入力で項目検索・選択

#### Step 5: Popup開閉イベントを理解する

PopupOpened/Closedを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | ComboBox.cs | `src/Avalonia.Controls/ComboBox.cs` | 487-503行目：PopupOpened |
| 5-2 | ComboBox.cs | `src/Avalonia.Controls/ComboBox.cs` | 475-485行目：PopupClosed |
| 5-3 | ComboBox.cs | `src/Avalonia.Controls/ComboBox.cs` | 513-531行目：TryFocusSelectedItem |

**主要処理フロー**:
- **487-503行目**: Popup開時に選択項目にフォーカス、親の可視性監視
- **475-485行目**: Popup閉時にフォーカス復帰
- **513-531行目**: 選択項目コンテナへのフォーカス

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

```
ComboBox
    │
    ├─ SelectingItemsControl（選択機能）
    │      ├─ SelectedIndex/SelectedItem
    │      ├─ SelectionChanged
    │      └─ ISelectionModel
    │
    ├─ Popup（PART_Popup）
    │      ├─ Open/Close
    │      ├─ Opened/Closed
    │      └─ IsInsidePopup
    │
    ├─ TextBox（PART_EditableTextBox）
    │      └─ IsEditable時の入力
    │
    ├─ ComboBoxItem（コンテナ）
    │      └─ IsSelected
    │
    ├─ SelectionBoxItem
    │      ├─ Rectangle + VisualBrush（Control時）
    │      └─ object（その他）
    │
    └─ VirtualizingStackPanel（仮想化パネル）
```

### データフロー図

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

クリック/キー入力
        │
        ▼
   IsDropDownOpen設定 ────▶ Popup.Open/Close
        │                       │
        ▼                       ▼
   PopupOpened/Closed ───────▶ イベント発火
        │                       │
        ▼                       ▼
ポインターリリース（Popup内）    TryFocusSelectedItem
        │                       │
        ▼                       ▼
   UpdateSelectionFromEvent ──▶ SelectedItem設定
        │                       │
        ▼                       ▼
   Popup.Close ────────────────▶ UpdateSelectionBoxItem
        │                       │
        ▼                       ▼
   SelectionChangedイベント     表示更新

テキスト入力（IsEditable）
        │
        ▼
   TextChanged ────────────────▶ Items検索
        │                       │
        ▼                       ▼
   SelectedItem設定 ───────────▶ UpdateInputTextFromSelection
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ComboBox.cs | `src/Avalonia.Controls/ComboBox.cs` | ソース | ComboBoxコントロール |
| SelectingItemsControl.cs | `src/Avalonia.Controls/Primitives/SelectingItemsControl.cs` | ソース | 選択機能基盤 |
| ComboBoxItem.cs | `src/Avalonia.Controls/ComboBoxItem.cs` | ソース | 項目コンテナ |
| Popup.cs | `src/Avalonia.Controls/Primitives/Popup.cs` | ソース | ポップアップ |
| TextBox.cs | `src/Avalonia.Controls/TextBox.cs` | ソース | 編集テキストボックス |
| TextSearch.cs | `src/Avalonia.Controls/TextSearch.cs` | ソース | テキスト検索 |
| VirtualizingStackPanel.cs | `src/Avalonia.Controls/VirtualizingStackPanel.cs` | ソース | 仮想化パネル |
| ComboBoxAutomationPeer.cs | `src/Avalonia.Controls/Automation/Peers/ComboBoxAutomationPeer.cs` | ソース | オートメーション対応 |
