# 画面設計書 30-Drag+Drop

## 概要

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

### 本画面の処理概要

本画面は、Avaloniaのドラッグ&ドロップ機能をデモンストレーションするためのページです。テキスト、ファイル、ビットマップ、カスタムデータ形式のドラッグソースと、Copy/Move操作のドロップターゲットを使用したデータ転送の実装方法を学習・検証できる環境を提供します。

**業務上の目的・背景**：ドラッグ&ドロップは、ユーザーが直感的にデータを移動・コピーできる重要なUIパターンです。ファイルエクスプローラからのファイルドロップ、リスト内のアイテム並べ替え、アプリケーション間のデータ転送など、様々な場面で使用されます。Avaloniaでは、DragDrop.DoDragDropAsyncとDragDrop.DropEvent/DragOverEventを使用してクロスプラットフォーム対応のドラッグ&ドロップを実装できます。

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

**主要な操作・処理内容**：
1. テキストデータのドラッグ&ドロップ
2. ファイルデータのドラッグ（アプリケーションのエントリアセンブリ）
3. ビットマップ画像のドラッグ&ドロップ
4. カスタムデータ形式のドラッグ&ドロップ
5. Copy/Move操作の切り替え
6. ドロップされたデータの表示（テキスト、ファイル内容、画像）

**画面遷移**：MainViewからHamburgerMenuナビゲーションを通じて遷移。画面内での追加遷移なし。

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

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 54 | DragDrop | 主機能 | ドラッグ&ドロップのデモ。要素間のデータ転送 |

## 画面種別

デモ / サンプル表示（インタラクティブ）

## URL/ルーティング

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

## 入出力項目

本画面には従来の入力フォームはありません。ドラッグ&ドロップによるデータ転送を行います。

| 項目名 | 種別 | データ型 | 説明 |
|--------|------|----------|------|
| DragMeText | ドラッグソース | string | テキストデータ |
| DragMeFiles | ドラッグソース | IStorageFile | ファイルデータ |
| DragMeBitmap | ドラッグソース | Bitmap | ビットマップ画像 |
| DragMeCustom | ドラッグソース | string | カスタム形式データ |
| CopyTarget | ドロップターゲット | - | Copy操作用 |
| MoveTarget | ドロップターゲット | - | Move操作用 |

## 表示項目

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| 説明テキスト | TextBlock | 「Example of Drag+Drop capabilities」 |
| DragStateText | TextBlock | テキストドラッグの状態表示 |
| DragStateFiles | TextBlock | ファイルドラッグの状態表示 |
| DragStateBitmap | TextBlock | ビットマップドラッグの状態表示 |
| DragStateCustom | TextBlock | カスタムドラッグの状態表示 |
| DropState | ContentControl | ドロップされたデータの表示（テキスト/画像） |

## イベント仕様

### 1-DragMeText領域でのポインター押下（ドラッグ開始）

PointerPressedイベントでDoDrag関数が呼び出される。DataTransferにテキストデータ（「Text was dragged {count} times」）を追加し、DragDrop.DoDragDropAsyncでドラッグ操作を開始。許可されるエフェクトはCopy/Move/Link。

### 2-DragMeFiles領域でのポインター押下（ドラッグ開始）

Assembly.GetEntryAssembly()からエントリポイントのファイルパスを取得し、StorageProvider.TryGetFileFromPathAsyncでIStorageFileを取得。DataTransferにFileデータを追加してドラッグ開始。許可されるエフェクトはCopyのみ。

### 3-DragMeBitmap領域でのポインター押下（ドラッグ開始）

AssetLoaderからimage1.jpgを読み込みBitmapを生成。DataTransferにBitmapデータを追加してドラッグ開始。許可されるエフェクトはCopyのみ。

### 4-DragMeCustom領域でのポインター押下（ドラッグ開始）

カスタムデータ形式（xxx-avalonia-controlcatalog-custom）でDataTransferにstring「Test123」を追加。許可されるエフェクトはCopy/Move。

### 5-ドロップターゲットへのDragOver

DragOverイベントハンドラで、ドロップ先がMoveTargetかCopyTargetかを判定し、対応するDragDropEffectsを設定。テキスト/ファイル/ビットマップ/カスタム形式のいずれかが含まれていない場合はDragDropEffects.Noneを設定。

### 6-ドロップターゲットへのDrop

Dropイベントハンドラで、データ形式を判定して対応する処理を実行：
- Text: TryGetText()で取得しDropState.Contentに表示
- File: TryGetFiles()で取得し、ファイル内容を読み取って表示
- Bitmap: TryGetValue(DataFormat.Bitmap)で取得しImageコントロールで表示
- Custom: カスタム形式の値を取得し「Custom: {value}」形式で表示

### 7-ドラッグ操作完了

DoDragDropAsyncの戻り値（DragDropEffects）に応じて状態テキストを更新：
- Move: 「Data was moved」
- Copy: 「Data was copied」
- Link: 「Data was linked」
- None: 「The drag operation was canceled」

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

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

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

## メッセージ仕様

| 種別 | メッセージID | メッセージ内容 | 表示条件 |
|------|-------------|---------------|----------|
| 情報 | - | Text was dragged {count} times | テキストドラッグ時 |
| 情報 | - | Data was moved | Move操作完了時 |
| 情報 | - | Data was copied | Copy操作完了時 |
| 情報 | - | Data was linked | Link操作完了時 |
| 情報 | - | The drag operation was canceled | ドラッグキャンセル時 |
| 情報 | - | File {name}: {content} | ファイルドロップ時 |
| 情報 | - | Folder {name}: items {count} | フォルダードロップ時 |
| 情報 | - | Custom: {value} | カスタムデータドロップ時 |

## 例外処理

- ファイル読み取り失敗時は例外が発生する可能性あり
- アセンブリ情報取得失敗時はファイルドラッグデータが追加されない

## 備考

- DataFormat.CreateStringApplicationFormatでカスタムデータ形式を作成
- DragDrop.AllowDrop="True"でドロップターゲットを有効化
- DragDropEffectsでCopy/Move/Link/Noneを指定
- DialogsPage.ReadTextFromFileを再利用してファイル内容を読み取り

---

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

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

### 推奨読解順序

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

まず、ドラッグ&ドロップで使用されるデータ形式を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | DragAndDropPage.xaml.cs | `samples/ControlCatalog/Pages/DragAndDropPage.xaml.cs` | _customFormatフィールド、DataFormat.Text/File/Bitmapの使用 |

**読解のコツ**: DataFormat<T>はジェネリック型で、型安全なデータ転送を実現します。

#### Step 2: 画面レイアウトを理解する

XAMLでドラッグソースとドロップターゲットの配置を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | DragAndDropPage.xaml | `samples/ControlCatalog/Pages/DragAndDropPage.xaml` | Border.draggableスタイル、DragDrop.AllowDrop属性 |

**主要処理フロー**:
1. **行5-12**: draggableスタイル定義
2. **行20-36**: ドラッグソース群（DragMeText/Files/Bitmap/Custom）
3. **行38-55**: ドロップターゲット群（CopyTarget/MoveTarget）
4. **行58**: DropState表示領域

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

ドラッグ&ドロップのロジックを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | DragAndDropPage.xaml.cs | `samples/ControlCatalog/Pages/DragAndDropPage.xaml.cs` | SetupDndメソッド、DoDrag/DragOver/Drop関数 |

**主要処理フロー**:
- **行18-19**: カスタムデータ形式の定義
- **行27-35**: テキストドラッグのセットアップ
- **行37-48**: ファイルドラッグのセットアップ
- **行50-53**: ビットマップドラッグのセットアップ
- **行66-95**: SetupDnd - 各データ形式共通のドラッグセットアップ
- **行71-95**: DoDrag - DragDrop.DoDragDropAsyncの呼び出しと結果処理
- **行97-114**: DragOver - ドラッグオーバー時のエフェクト設定
- **行116-167**: Drop - ドロップ時のデータ処理

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

```
DragAndDropPage (UserControl)
    │
    ├─ コンストラクタ
    │      ├─ SetupDnd("Text", ...) → テキストドラッグ設定
    │      ├─ SetupDnd("Custom", ...) → カスタムドラッグ設定
    │      ├─ SetupDnd("Files", ...) → ファイルドラッグ設定
    │      └─ SetupDnd("Bitmap", ...) → ビットマップドラッグ設定
    │
    ├─ SetupDnd(suffix, factory, effects)
    │      ├─ DoDrag (PointerPressed)
    │      │      ├─ factory(DataTransfer) → データ追加
    │      │      └─ DragDrop.DoDragDropAsync
    │      │             └─ 結果に応じてdragState.Text更新
    │      │
    │      ├─ DragOver (DragDrop.DragOverEvent)
    │      │      ├─ MoveTarget判定 → Move効果
    │      │      └─ CopyTarget判定 → Copy効果
    │      │
    │      └─ Drop (DragDrop.DropEvent)
    │             ├─ Contains(Text) → TryGetText()
    │             ├─ Contains(File) → TryGetFiles() → ReadTextFromFile
    │             ├─ Contains(Bitmap) → TryGetValue(Bitmap) → Image
    │             └─ Contains(_customFormat) → TryGetValue()
    │
    └─ AddHandler
           ├─ DragDrop.DropEvent → Drop
           └─ DragDrop.DragOverEvent → DragOver
```

### データフロー図

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

PointerPressed ─────────▶ DoDrag ──────────────────────────▶ ドラッグ開始
                              │
                              └─ factory(DataTransfer)
                                     ├─ DataTransferItem.Create(Text, value)
                                     ├─ DataTransferItem.Create(File, storageFile)
                                     ├─ DataTransferItem.Create(Bitmap, bitmap)
                                     └─ DataTransferItem.Create(_customFormat, value)

DragOver ───────────────▶ DragDropEffects判定 ──────────────▶ カーソル変更
                              │
                              ├─ MoveTarget → DragDropEffects.Move
                              └─ CopyTarget → DragDropEffects.Copy

Drop ───────────────────▶ データ形式判定 ──────────────────▶ DropState更新
                              │
                              ├─ Text → string表示
                              ├─ File → ファイル内容読み取り
                              ├─ Bitmap → Image表示
                              └─ Custom → "Custom: {value}"

DoDragDropAsync完了 ────▶ DragDropEffects ──────────────────▶ 状態テキスト更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| DragAndDropPage.xaml | `samples/ControlCatalog/Pages/DragAndDropPage.xaml` | XAML | 画面レイアウト定義 |
| DragAndDropPage.xaml.cs | `samples/ControlCatalog/Pages/DragAndDropPage.xaml.cs` | ソース | コードビハインド、ドラッグ&ドロップロジック |
| DialogsPage.xaml.cs | `samples/ControlCatalog/Pages/DialogsPage.xaml.cs` | ソース | ReadTextFromFileメソッドの参照 |
| image1.jpg | `samples/ControlCatalog/Assets/image1.jpg` | アセット | ビットマップドラッグ用画像 |
