# 画面設計書 21-ContextFlyout

## 概要

本ドキュメントは、Avalonia ControlCatalogサンプルアプリケーションにおけるContextFlyoutデモページの画面設計を定義するものです。

### 本画面の処理概要

本画面は、ContextFlyout（コンテキストフライアウト）コントロールの各種使用パターンをデモンストレーションするためのページです。右クリック時にフライアウト形式のメニューを表示する機能を、開発者が学習・検証できる環境を提供します。

**業務上の目的・背景**：ContextFlyoutは、ユーザーがコントロール上で右クリックした際にポップアップ表示されるフライアウトメニューを実装するための機能です。ContextMenuとは異なり、MenuFlyoutやカスタムFlyoutなど柔軟なUI構成が可能です。デスクトップアプリケーションにおいて、コンテキストに応じた操作メニューを提供するための標準的なUXパターンを実現します。

**画面へのアクセス方法**：ControlCatalogアプリケーションのメインウィンドウから、HamburgerMenuのナビゲーションで「ContextFlyout」を選択することでアクセスできます。

**主要な操作・処理内容**：
1. XAMLで定義されたMenuFlyoutの表示（標準メニュー項目、無効化項目、サブメニュー、アイコン付き項目、チェックボックス付き項目）
2. ViewModelを介した動的メニュー生成とバインディング
3. カスタムContextRequestedハンドラによるフライアウト制御
4. Opening/Closingイベントのキャンセル機能
5. TextBox用のカスタムContextFlyout（Cut/Copy/Paste/Clear操作）
6. ネストされたContextFlyoutの表示

**画面遷移**：MainViewからHamburgerMenuナビゲーションを通じて遷移。画面内でのダイアログ表示（ファイルピッカー）機能あり。

**権限による表示制御**：特になし（サンプルアプリケーション）

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 19 | ContextMenu | 主機能 | ContextFlyoutのデモ。右クリックフライアウト表示 |

## 画面種別

デモ / サンプル表示

## URL/ルーティング

HamburgerMenu内部ナビゲーション（直接URLルーティングなし）

## 入出力項目

| 項目名 | 種別 | データ型 | 必須 | 説明 |
|--------|------|----------|------|------|
| TextBox入力値 | 入力 | string | - | Cut/Copy/Paste操作対象のテキスト |
| CancelOpenCheckBox | 入力 | bool | - | フライアウトのオープンをキャンセルするかどうか |
| CancelCloseCheckBox | 入力 | bool | - | フライアウトのクローズをキャンセルするかどうか |

## 表示項目

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| 説明テキスト | string | 「A right click Flyout that can be applied to any control.」 |
| デモ領域（Defined in XAML） | Border | XAMLで定義されたMenuFlyout |
| デモ領域（Dynamically Generated） | Border | ViewModelからバインドされた動的メニュー |
| デモ領域（Custom ContextRequested handler） | Border | カスタムハンドラでのポインター位置表示 |
| デモ領域（Cancellable） | Border | Opening/Closingキャンセル可能なFlyout |
| カスタムTextBox用Flyout | TextBox + Flyout | Cut/Copy/Paste/Clearボタン |

## イベント仕様

### 1-右クリック（Defined in XAML領域）

XAMLで定義されたMenuFlyoutが表示される。メニュー項目：
- Standard Menu Item（Ctrl+A）
- Disabled Menu Item（無効化、Ctrl+D）
- Menu with Submenu（サブメニュー2階層）
- Menu Item with Icon（GitHubアイコン）
- Menu Item with Checkbox（チェックボックス付き）

### 2-右クリック（Dynamically Generated領域）

ViewModelのMenuItemsコレクションからバインドされたメニューが表示される。Open/Save/Recentなどの項目が動的に構成される。

### 3-右クリック（Custom ContextRequested handler領域）

CustomContextRequestedハンドラが呼び出され、ポインター位置が取得・表示される。e.Handled=trueによりデフォルトのフライアウト表示が抑制される。

### 4-右クリック（Cancellable領域）

CancelOpenCheckBoxがチェックされている場合、Opening時にキャンセルされフライアウトが表示されない。CancelCloseCheckBoxがチェックされている場合、Closing時にキャンセルされフライアウトが閉じない。

### 5-TextBox右クリック

カスタムフライアウトが表示され、Cut/Copy/Paste/Clearボタンが利用可能。各ボタンはTextBoxの対応するコマンドにバインドされ、IsEnabledも連動する。

### 6-Cut/Copy/Paste/Clearボタンクリック

対応するTextBox操作が実行され、CloseFlyoutメソッドによりフライアウトが閉じられる。

## データベース更新仕様

### 操作別データベース影響一覧

本画面はUIコントロールのデモであり、データベース操作は行いません。

## メッセージ仕様

| 種別 | メッセージID | メッセージ内容 | 表示条件 |
|------|-------------|---------------|----------|
| 情報 | - | Context was requested with pointer at: {X}, {Y} | Custom ContextRequested handler領域で右クリック時 |
| 情報 | - | Context was requested without pointer | キーボード操作でコンテキスト要求時 |

## 例外処理

- 特になし（デモ画面のため例外発生時はデバッグ出力のみ）

## 備考

- ContextFlyoutはContextMenuの代替として、より柔軟なフライアウトUI構成が可能
- TextBox.ContextMenuを{x:Null}に設定することで、デフォルトのコンテキストメニューを無効化
- FlyoutPresenterClassesを使用してフライアウトのスタイルをカスタマイズ可能

---

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

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

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、メニュー項目を表現するViewModelの構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ContextPageViewModel.cs | `samples/ControlCatalog/ViewModels/ContextPageViewModel.cs` | MenuItemsコレクション、Open/Save/OpenRecentコマンドの定義（行12-43） |
| 1-2 | MenuItemViewModel.cs | `samples/ControlCatalog/ViewModels/MenuItemViewModel.cs` | メニュー項目のHeader、Command、Items、CommandParameterプロパティ |

**読解のコツ**: MiniMvvmフレームワークのMiniCommandクラスがコマンドパターンを実装しています。

#### Step 2: エントリーポイントを理解する

処理の起点となるUserControlとXAMLレイアウトを特定します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ContextFlyoutPage.xaml | `samples/ControlCatalog/Pages/ContextFlyoutPage.xaml` | Border.ContextFlyoutプロパティへのMenuFlyout設定、スタイル定義、バインディング構文 |

**主要処理フロー**:
1. **行11-15**: FlyoutPresenterのNoPaddingスタイル定義
2. **行32-58**: XAML定義のMenuFlyout（静的メニュー構成）
3. **行60-73**: ViewModelバインドの動的MenuFlyout
4. **行74-81**: カスタムContextRequestedハンドラ
5. **行82-93**: キャンセル可能なFlyout
6. **行98-157**: TextBox用カスタムFlyout（Cut/Copy/Paste/Clear）

#### Step 3: コードビハインドを理解する

イベントハンドラとデータコンテキスト設定を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ContextFlyoutPage.xaml.cs | `samples/ControlCatalog/Pages/ContextFlyoutPage.xaml.cs` | コンストラクタでのDataContext設定、各イベントハンドラの実装 |

**主要処理フロー**:
- **行11-15**: コンストラクタでContextPageViewModelをDataContextに設定
- **行29-32**: ContextFlyoutPage_Closing - クローズキャンセル処理
- **行34-40**: ContextFlyoutPage_Opening - オープンキャンセル処理
- **行42-45**: CloseFlyout - TextBoxフライアウトを閉じる
- **行47-56**: CustomContextRequested - ポインター位置取得と表示

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

```
ContextFlyoutPage (UserControl)
    │
    ├─ コンストラクタ
    │      └─ ContextPageViewModel生成 → DataContext設定
    │
    ├─ XAML定義MenuFlyout
    │      └─ MenuItem群（静的定義）
    │
    ├─ 動的MenuFlyout
    │      └─ MenuItems (ItemsSource) → MenuItemViewModel群
    │             ├─ OpenCommand → Open() → StorageProvider.OpenFilePickerAsync
    │             ├─ SaveCommand → Save() → Debug出力
    │             └─ OpenRecentCommand → OpenRecent(path)
    │
    ├─ CustomContextRequested
    │      └─ TryGetPosition() → TextBlock.Text更新
    │
    ├─ Opening/Closingイベント
    │      └─ CancelEventArgs.Cancel設定
    │
    └─ TextBox.ContextFlyout
           └─ CloseFlyout → Flyout.Hide()
```

### データフロー図

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

右クリック ───────────▶ ContextRequested発生 ───────────▶ Flyout表示
                              │
                              └─ e.Handled=true時 ─────▶ カスタム処理

CheckBox状態 ───────────▶ Opening/Closingハンドラ ──────▶ キャンセル判定
                              │
                              └─ e.Cancel=true時 ──────▶ 表示/非表示制御

TextBox操作 ────────────▶ Cut/Copy/Paste/Clearコマンド ─▶ TextBox内容更新
                              │
                              └─ CloseFlyout() ─────────▶ Flyout.Hide()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ContextFlyoutPage.xaml | `samples/ControlCatalog/Pages/ContextFlyoutPage.xaml` | XAML | 画面レイアウト定義 |
| ContextFlyoutPage.xaml.cs | `samples/ControlCatalog/Pages/ContextFlyoutPage.xaml.cs` | ソース | コードビハインド、イベントハンドラ |
| ContextPageViewModel.cs | `samples/ControlCatalog/ViewModels/ContextPageViewModel.cs` | ソース | メニュー項目とコマンドの定義 |
| MenuItemViewModel.cs | `samples/ControlCatalog/ViewModels/MenuItemViewModel.cs` | ソース | メニュー項目データモデル |
| github_icon.png | `samples/ControlCatalog/Assets/github_icon.png` | アセット | メニューアイコン画像 |
