# 通知設計書 5-カスタム通知

## 概要

本ドキュメントは、Avalonia UIフレームワークにおけるカスタム通知の設計について記述する。カスタム通知は、任意のコントロールを通知として表示可能にする仕組みであり、IManagedNotificationManager.Show(object content) で実装される。

### 本通知の処理概要

カスタム通知は、標準の Notification クラスでは表現できない高度なUIコンテンツを通知として表示するための仕組みである。

**業務上の目的・背景**：標準的なタイトルとメッセージだけでは不十分な場合、アプリケーション固有のUIコンポーネント（ボタン、画像、プログレスバー、入力フィールドなど）を含む通知が必要となる。カスタム通知により、ユーザーに対してインタラクティブな通知を提供し、通知内で直接アクションを実行させることができる。例えば、「はい/いいえ」ボタン付きの確認通知、進捗表示付きのダウンロード通知、プレビュー画像付きの通知などが実現可能となる。

**通知の送信タイミング**：アプリケーションコードから `IManagedNotificationManager.Show(object content)` メソッドが呼び出されたとき。開発者が任意のオブジェクト（通常は UserControl やその ViewModel）を通知として表示する。

**通知の受信者**：アプリケーションのUI上で通知が表示されるウィンドウを視認しているエンドユーザー。カスタムUIによるインタラクションが可能な通知のため、能動的なユーザー参加が期待される。

**通知内容の概要**：開発者が定義した任意のコンテンツ。UserControl、DataTemplate、または任意のAvaloniaコントロールを使用できる。内容は完全にカスタマイズ可能であり、ボタン、画像、テキスト、入力フィールドなどを自由に配置できる。

**期待されるアクション**：通知内に配置されたボタンのクリック、入力の実行など、カスタムUIが提供するアクションをユーザーが実行する。NotificationCard.CloseOnClick 添付プロパティを設定したボタンをクリックすると、通知が自動的に閉じる。

## 通知種別

アプリ内通知（In-Window Notification） - カスタムコンテンツ

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（UIスレッド上で実行） |
| 優先度 | 通常（コンテンツに応じたカスタムスタイル適用可能） |
| リトライ | なし |

### 送信先決定ロジック

WindowNotificationManager が配置されている TopLevel の AdornerLayer 上に通知カードが追加される。カスタムコンテンツは NotificationCard の Content プロパティに設定される。

## 通知テンプレート

### カスタム通知の場合

| 項目 | 内容 |
|-----|------|
| 表示位置 | NotificationPosition で指定（デフォルト: TopRight） |
| 最大表示数 | MaxItems で指定（デフォルト: 5） |
| スタイル | INotification でない場合は `:information` がデフォルト |

### 本文テンプレート（サンプル: CustomNotificationView.xaml）

```xml
<UserControl>
    <Border Padding="12" MinHeight="20" Background="DodgerBlue">
        <Grid ColumnDefinitions="Auto,*">
            <Panel>
                <!-- アイコン -->
            </Panel>
            <DockPanel>
                <TextBlock Text="{Binding Title}" />
                <StackPanel Orientation="Horizontal">
                    <Button Content="No" NotificationCard.CloseOnClick="True" />
                    <Button Content="Yes" NotificationCard.CloseOnClick="True" />
                </StackPanel>
                <TextBlock Text="{Binding Message}" />
            </DockPanel>
        </Grid>
    </Border>
</UserControl>
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | UI通知のため添付ファイルは存在しない |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| 任意 | カスタムViewModelのプロパティ | DataContext | カスタム定義 |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API呼び出し | IManagedNotificationManager.Show(object) | content が INotification でない | カスタムコンテンツ表示 |
| API呼び出し | WindowNotificationManager.Show(object, NotificationType, ...) | 直接呼び出し | タイプ指定でカスタム表示 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| UIスレッド外からの呼び出し | Dispatcher.UIThread.VerifyAccess() で検証される |
| WindowNotificationManager 未配置 | 通知マネージャーがウィンドウに配置されていない場合は表示されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[IManagedNotificationManager.Show 呼び出し] --> B{content は INotification?}
    B -->|Yes| C[INotification として処理]
    B -->|No| D[カスタムコンテンツとして処理]
    D --> E[NotificationType.Information がデフォルト]
    E --> F[NotificationCard 作成]
    F --> G[Content = カスタムオブジェクト]
    G --> H[:information 疑似クラス適用]
    H --> I[_items に追加]
    I --> J{MaxItems 超過?}
    J -->|Yes| K[最古の通知をクローズ]
    J -->|No| L[表示完了]
    K --> L
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| なし | - | UI通知のためデータベースは使用しない |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | UI通知のためデータベースは使用しない |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| InvalidOperationException | UIスレッド外からの呼び出し | Dispatcher.UIThread.Post() を使用 |
| NullReferenceException | NotificationManager が null | WindowNotificationManager を正しく配置 |
| DataTemplate未設定 | カスタムオブジェクトの表示テンプレートがない | DataTemplate を定義するか UserControl を使用 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし（MaxItems で同時表示数を制限） |
| 1日あたり上限 | なし |

### 配信時間帯

特になし（アプリケーション実行中はいつでも表示可能）

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

- カスタムコンテンツ内のユーザー入力を適切にバリデーションすること
- 通知内で実行されるコマンドの権限を確認すること
- 外部データをバインドする場合はエスケープ処理を行うこと

## 備考

- カスタム通知は DataTemplate または UserControl を使用して実装する
- NotificationCard.CloseOnClick 添付プロパティをボタンに設定すると、クリック時に通知が閉じる
- INotification を実装したカスタムクラスを作成することで、標準の通知プロパティ（Title, Message, Type, Expiration）を利用しつつカスタムUIを適用することも可能
- classes パラメータを使用してカスタムスタイルクラスを適用可能

---

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

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

### 推奨読解順序

#### Step 1: インターフェースを理解する

カスタム通知を可能にする IManagedNotificationManager を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | IManagedNotificationManager.cs | `src/Avalonia.Controls/Notifications/IManagedNotificationManager.cs` | Show(object content) メソッドの定義 |
| 1-2 | WindowNotificationManager.cs | `src/Avalonia.Controls/Notifications/WindowNotificationManager.cs` | Show(object) の実装 |

**読解のコツ**: IManagedNotificationManager は INotificationManager を継承し、任意のオブジェクトを表示できる Show(object) を追加している。

#### Step 2: 表示ロジックを理解する

カスタムコンテンツの表示処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | WindowNotificationManager.cs | `src/Avalonia.Controls/Notifications/WindowNotificationManager.cs` | Show(object) での分岐処理 |

**主要処理フロー**:
1. **103-113行目**: Show(object) で INotification かどうかを判定
2. **110-112行目**: INotification でない場合は `NotificationType.Information` をデフォルトで使用
3. **124-137行目**: NotificationCard 作成時に Content にカスタムオブジェクトを設定

#### Step 3: CloseOnClick を理解する

ボタンクリックで通知を閉じる機能を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | NotificationCard.cs | `src/Avalonia.Controls/Notifications/NotificationCard.cs` | CloseOnClick 添付プロパティ |

**主要処理フロー**:
- **91-107行目**: CloseOnClick プロパティの定義と設定メソッド
- **109-121行目**: プロパティ変更時にボタンの Click イベントを登録
- **126-131行目**: Button_Click で NotificationCard を取得してクローズ

#### Step 4: サンプル実装を理解する

実際のカスタム通知の実装例を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | CustomNotificationView.xaml | `samples/ControlCatalog/Views/CustomNotificationView.xaml` | カスタム通知のUIレイアウト |
| 4-2 | NotificationViewModel.cs | `samples/ControlCatalog/ViewModels/NotificationViewModel.cs` | カスタム通知の呼び出し方法 |

**主要処理フロー**:
- **14行目（ViewModel）**: `NotificationManager?.Show(new NotificationViewModel() { ... }, NotificationType.Warning)` でカスタム通知を表示
- **14-15行目（View）**: `NotificationCard.CloseOnClick="True"` でボタンクリック時に通知をクローズ

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

```
アプリケーションコード
    │
    ├─ new NotificationViewModel() { Title = "...", Message = "..." }
    │
    └─ IManagedNotificationManager.Show(viewModel, NotificationType.Warning)
           │
           └─ WindowNotificationManager.Show(object, NotificationType, ...)
                  │
                  ├─ new NotificationCard { Content = viewModel }
                  │
                  ├─ DataTemplate/UserControl でレンダリング
                  │      └─ CustomNotificationView.xaml
                  │
                  └─ Button.Click → NotificationCard.Close()
                         └─ NotificationCard.CloseOnClick が True の場合
```

### データフロー図

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

ViewModel/UserControl    WindowNotificationManager          NotificationCard
├─ Title         ───▶   ├─ INotification判定         ───▶   ├─ Content = ViewModel
├─ Message              ├─ NotificationCard作成             ├─ DataTemplate適用
├─ Commands             └─ _items追加                       ├─ UserControl表示
└─ Properties                                               └─ インタラクティブUI
       │
       └─ Button.Click → NotificationCard.Close()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| IManagedNotificationManager.cs | `src/Avalonia.Controls/Notifications/IManagedNotificationManager.cs` | ソース | Show(object) の定義 |
| WindowNotificationManager.cs | `src/Avalonia.Controls/Notifications/WindowNotificationManager.cs` | ソース | カスタム通知の表示ロジック |
| NotificationCard.cs | `src/Avalonia.Controls/Notifications/NotificationCard.cs` | ソース | CloseOnClick 添付プロパティ |
| CustomNotificationView.xaml | `samples/ControlCatalog/Views/CustomNotificationView.xaml` | サンプル | カスタム通知のUI例 |
| NotificationViewModel.cs | `samples/ControlCatalog/ViewModels/NotificationViewModel.cs` | サンプル | カスタム通知の使用例 |
