# 通知設計書 8-PropertyChanged

## 概要

本ドキュメントは、Avalonia UIフレームワークにおけるPropertyChanged（プロパティ変更）通知の設計について記述する。PropertyChanged通知は、INotifyPropertyChanged インターフェースを通じてプロパティ値の変更を通知するための標準的な.NETの仕組みである。

### 本通知の処理概要

PropertyChanged通知は、オブジェクトのプロパティ値が変更されたことをデータバインディングシステムやその他のリスナーに通知するための仕組みである。

**業務上の目的・背景**：MVVMパターンを採用するアプリケーションにおいて、ViewModelのプロパティが変更されたときにUIを自動的に更新する必要がある。PropertyChangedイベントは、このような双方向データバインディングの基盤となる。ユーザーがデータを変更した場合、または外部ソースからデータが更新された場合に、UIが最新の状態を反映できるようになる。

**通知の送信タイミング**：プロパティのセッターが呼び出され、値が実際に変更されたとき。OnPropertyChanged() メソッドまたは同等の仕組みを通じて PropertyChanged イベントが発火される。

**通知の受信者**：PropertyChanged イベントをサブスクライブしているリスナー。主にデータバインディングシステム（InpcPropertyAccessorPlugin）、UI要素、その他のオブザーバーが受信者となる。

**通知内容の概要**：PropertyChangedEventArgs オブジェクトとして表現され、変更されたプロパティの名前（PropertyName）が含まれる。Notification クラスの Title や Message プロパティなど、INotifyPropertyChanged を実装するクラスのプロパティ変更を追跡できる。

**期待されるアクション**：バインディングシステムがプロパティの新しい値を取得し、バインドされているUI要素を更新する。

## 通知種別

イベント通知（.NET 標準の INotifyPropertyChanged インターフェース）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（イベント発火） |
| 優先度 | 通常 |
| リトライ | なし |

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

PropertyChanged イベントをサブスクライブしているすべてのハンドラに通知が送信される。バインディングシステムは InpcPropertyAccessorPlugin を通じてこのイベントを監視し、プロパティ値の変更を検知する。

## 通知テンプレート

### PropertyChanged イベントの場合

| 項目 | 内容 |
|-----|------|
| イベント名 | PropertyChanged |
| イベント引数型 | PropertyChangedEventArgs |
| プロパティ名 | PropertyChangedEventArgs.PropertyName |

### イベント内容

```csharp
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
```

### 添付ファイル

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

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| PropertyName | 変更されたプロパティの名前 | [CallerMemberName] または明示指定 | Yes |
| sender | イベント発生元オブジェクト | this | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| プロパティ変更 | セッター実行 | 値が変更された | 標準的なプロパティ変更 |
| 手動発火 | OnPropertyChanged 呼び出し | 明示的な発火 | 複数プロパティの一括更新など |
| 全プロパティ更新 | PropertyName = "" または null | すべてのプロパティ | オブジェクト全体の更新 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 値が同じ | 新旧の値が等しい場合は発火しない（推奨パターン） |
| イベント未サブスクライブ | ハンドラがない場合はイベント発火されない |

## 処理フロー

### PropertyChanged 発火フロー

```mermaid
flowchart TD
    A[プロパティセッター呼び出し] --> B{値が変更された?}
    B -->|No| C[何もしない]
    B -->|Yes| D[フィールドに新しい値を設定]
    D --> E[OnPropertyChanged呼び出し]
    E --> F{PropertyChanged イベントあり?}
    F -->|No| G[終了]
    F -->|Yes| H[PropertyChanged.Invoke]
    H --> I[リスナーに通知]
    I --> J[バインディング更新]
    J --> K[UI更新]
    G --> L[処理完了]
    K --> L
```

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

### 参照テーブル一覧

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

### 更新テーブル一覧

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

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| PropertyName 不正 | 存在しないプロパティ名 | [CallerMemberName] を使用して自動取得 |
| スレッド問題 | UIスレッド外からの更新 | Dispatcher を使用 |
| メモリリーク | イベントハンドラ未解除 | WeakEvent パターンを使用 |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし |
| 1日あたり上限 | なし |

### 配信時間帯

プロパティ変更時（アプリケーション実行中、常時）

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

- 機密プロパティの変更通知がデバッグ出力に露出しないよう注意
- イベントハンドラの追加/削除を適切に管理してメモリリークを防止

## 備考

- Notification クラスは INotifyPropertyChanged を実装している
- [CallerMemberName] 属性を使用することでプロパティ名を自動取得可能
- Avalonia の InpcPropertyAccessorPlugin がこのイベントを監視してバインディングを更新
- WeakEvents クラスを使用して弱参照イベントハンドラを実装可能

---

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

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

### 推奨読解順序

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

INotifyPropertyChanged インターフェースの使用方法を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Notification.cs | `src/Avalonia.Controls/Notifications/Notification.cs` | INotifyPropertyChanged の実装例 |

**読解のコツ**: Notification.cs の15行目で INotifyPropertyChanged を実装。91行目で PropertyChanged イベントを定義。

#### Step 2: 実装パターンを理解する

PropertyChanged イベントの発火パターンを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Notification.cs | `src/Avalonia.Controls/Notifications/Notification.cs` | OnPropertyChanged メソッドの実装 |

**主要処理フロー**:
- **52-63行目**: Title プロパティのセッター
  - 値が異なる場合のみフィールドを更新
  - OnPropertyChanged() を呼び出し
- **93-96行目**: OnPropertyChanged メソッド
  - [CallerMemberName] でプロパティ名を自動取得
  - PropertyChanged?.Invoke で通知

#### Step 3: バインディングシステムとの連携を理解する

InpcPropertyAccessorPlugin による監視を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | InpcPropertyAccessorPlugin.cs | `src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs` | INotifyPropertyChanged の監視 |

**主要処理フロー**:
- PropertyChanged イベントをサブスクライブ
- プロパティ名が一致したら値を再取得してバインディングを更新

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

```
ViewModel / モデル
    │
    ├─ プロパティセッター
    │      │
    │      ├─ 値の変更チェック
    │      ├─ フィールドに値を設定
    │      └─ OnPropertyChanged(propertyName)
    │             │
    │             └─ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName))
    │                    │
    │                    ├─ InpcPropertyAccessorPlugin
    │                    │      └─ プロパティ値を再取得
    │                    │             └─ バインディング更新
    │                    │
    │                    └─ 他のリスナー
    │
    └─ UI更新
```

### データフロー図

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

プロパティ変更           INotifyPropertyChanged              イベント
├─ 新しい値       ───▶   ├─ 値の変更チェック        ───▶    ├─ PropertyChangedEventArgs
├─ プロパティ名          ├─ フィールド更新                   │      └─ PropertyName
└─ sender               └─ PropertyChanged.Invoke           │
                                │                            └─ バインディング更新
                                ▼                                    │
                         InpcPropertyAccessorPlugin                  ▼
                         └─ プロパティ値を再取得             UI要素の更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Notification.cs | `src/Avalonia.Controls/Notifications/Notification.cs` | ソース | INotifyPropertyChanged 実装例 |
| InpcPropertyAccessorPlugin.cs | `src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs` | ソース | PropertyChanged 監視 |
| WeakEvents.cs | `src/Avalonia.Base/Utilities/WeakEvents.cs` | ソース | 弱参照イベント |
| ViewModelBase.cs | `samples/MiniMvvm/ViewModelBase.cs` | サンプル | ViewModel 基底クラス |
| PropertyChangedExtensions.cs | `samples/MiniMvvm/PropertyChangedExtensions.cs` | サンプル | 拡張メソッド |
