# 通知設計書 3-INotifyDataErrorInfo.ErrorsChanged

## 概要

本ドキュメントは、.NET Runtimeにおける`INotifyDataErrorInfo.ErrorsChanged`イベント通知の設計を記述する。このイベントは、オブジェクトのデータ検証エラーの状態が変化した際にリスナーに通知を行うためのメカニズムを提供する。

### 本通知の処理概要

`INotifyDataErrorInfo.ErrorsChanged`イベントは、オブジェクトのプロパティに対するデータ検証エラーが追加、削除、または変更された際に外部のリスナーに通知するためのイベントである。このインターフェースは非同期検証をサポートし、UIフレームワークでの入力検証とエラー表示に使用される。

**業務上の目的・背景**：ユーザー入力のバリデーションはアプリケーション開発において重要な要素である。従来の`IDataErrorInfo`インターフェースは同期的な検証のみをサポートしていたが、サーバーサイドバリデーションなど非同期処理が必要なシナリオに対応できなかった。`INotifyDataErrorInfo`は非同期検証をサポートし、検証状態の変化をUIに即座に反映させることを可能にする。WPF、UWP、Xamarin Forms、MAUIなどのUIフレームワークで入力検証のために使用される。

**通知の送信タイミング**：プロパティの検証エラーが追加された時、削除された時、またはエラー内容が変更された時に発火する。非同期検証の完了後に発火することも可能。

**通知の受信者**：`ErrorsChanged`イベントを購読しているすべてのイベントハンドラが受信者となる。一般的にはUIフレームワークのバリデーションシステム（WPFのValidation.ErrorsやBindingExpression等）がリスナーとなる。

**通知内容の概要**：`DataErrorsChangedEventArgs`オブジェクトを通じて、エラー状態が変化したプロパティの名前（`PropertyName`）が通知される。プロパティ名がnullまたは空文字列の場合は、オブジェクトレベルのエラーまたはすべてのプロパティのエラーが変化したことを示す。

**期待されるアクション**：受信者は`GetErrors(propertyName)`メソッドを呼び出して最新のエラー情報を取得し、UI上のエラー表示を更新する。

## 通知種別

インターフェースイベント（アプリ内通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（非同期検証完了後のUI通知は適切なスレッドで） |
| 優先度 | 中 |
| リトライ | なし（同期イベント） |

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

`ErrorsChanged`イベントに登録されているすべてのイベントハンドラに対して、マルチキャストデリゲートとして通知が行われる。

## 通知テンプレート

### イベント引数

| 項目 | 内容 |
|-----|------|
| イベント型 | `EventHandler<DataErrorsChangedEventArgs>` |
| 引数型 | `DataErrorsChangedEventArgs` |
| sender | イベントを発火したオブジェクト（通常は`this`） |

### INotifyDataErrorInfoインターフェース

```csharp
public interface INotifyDataErrorInfo
{
    bool HasErrors { get; }
    IEnumerable GetErrors(string? propertyName);
    event EventHandler<DataErrorsChangedEventArgs>? ErrorsChanged;
}
```

### DataErrorsChangedEventArgs

```csharp
public class DataErrorsChangedEventArgs : EventArgs
{
    public DataErrorsChangedEventArgs(string? propertyName);
    public virtual string? PropertyName { get; }
}
```

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| PropertyName | エラー状態が変化したプロパティの名前 | 実装クラスのプロパティ名 | No（nullでオブジェクトレベルエラーを示す） |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| プログラム実行 | 検証エラーの追加 | エラーリストにエラーが追加された | 新しいエラーが検出された |
| プログラム実行 | 検証エラーの削除 | エラーリストからエラーが削除された | エラーが解消された |
| プログラム実行 | 非同期検証の完了 | 非同期検証が完了しエラー状態が変化 | サーバーサイドバリデーション等 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| エラー状態が同一 | エラーの追加・削除がない場合はイベントを発火しない |
| 初期化中 | オブジェクトの初期化中はイベントを発火しないことがある |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[プロパティ値の変更] --> B[検証ロジックの実行]
    B --> C{検証エラーあり?}
    C -->|Yes| D[エラーリストにエラーを追加]
    C -->|No| E{既存エラーあり?}
    E -->|Yes| F[エラーリストからエラーを削除]
    E -->|No| G[終了]
    D --> H[OnErrorsChangedメソッド呼び出し]
    F --> H
    H --> I{ErrorsChangedイベントハンドラが登録されているか?}
    I -->|No| G
    I -->|Yes| J[ErrorsChangedイベントを発火]
    J --> K[各イベントハンドラが実行される]
    K --> L[UIがGetErrorsを呼び出しエラー表示を更新]
    L --> G
```

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

### 参照テーブル一覧

該当なし（メモリ内イベント通知）

### 更新テーブル一覧

該当なし（メモリ内イベント通知）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| NullReferenceException | イベントハンドラがnullの状態でInvokeを試みた場合 | null条件演算子（?.）を使用 |
| GetErrors内例外 | エラー情報の取得中に例外が発生した場合 | 空のコレクションを返す |
| スレッドアクセス例外 | 非同期検証完了後にUIスレッド以外から発火 | Dispatcherを使用してUIスレッドで発火 |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

制限なし（いつでも発火可能）

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

- エラーメッセージに機密情報（パスワードの一部、個人情報等）を含めないこと
- エラーメッセージのローカライズ対応を考慮
- サーバーサイドバリデーション結果をそのまま表示する場合は、インジェクション攻撃に注意

## 備考

- `INotifyDataErrorInfo`は`IDataErrorInfo`の後継インターフェース
- 非同期検証をサポートするため、`HasErrors`プロパティと`GetErrors`メソッドも提供
- `GetErrors(null)`または`GetErrors(string.Empty)`でオブジェクトレベルのエラーを取得
- `HasErrors`プロパティは全プロパティにエラーがあるかどうかを示す
- WPF 4.5以降、UWP、Xamarin Forms、MAUIでネイティブサポート

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | DataErrorsChangedEventArgs.cs | `src/libraries/System.ObjectModel/src/System/ComponentModel/DataErrorsChangedEventArgs.cs` | PropertyNameプロパティの定義とコンストラクタを確認 |

**読解のコツ**: `PropertyChangedEventArgs`と同様の構造。`PropertyName`がnullまたは空文字列の場合はオブジェクトレベルのエラーを示す。

**主要処理フロー**:
1. **行9**: `DataErrorsChangedEventArgs`クラスの定義
2. **行15-18**: コンストラクタでPropertyNameを設定
3. **行23**: `PropertyName`プロパティ

#### Step 2: インターフェース定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | INotifyDataErrorInfo.cs | `src/libraries/System.ObjectModel/src/System/ComponentModel/INotifyDataErrorInfo.cs` | インターフェースの3つのメンバーを確認（行8-14） |

**主要処理フロー**:
1. **行8**: `INotifyDataErrorInfo`インターフェースの定義
2. **行10**: `HasErrors`プロパティ（エラーの有無を示す）
3. **行12**: `GetErrors`メソッド（指定プロパティのエラーを取得）
4. **行14**: `ErrorsChanged`イベント

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

```
プロパティsetter（実装例）
    │
    ├─ ValidateProperty(value, propertyName)  // 検証ロジック
    │      │
    │      ├─ 検証エラーあり
    │      │      └─ AddError(propertyName, errorMessage)
    │      │             └─ OnErrorsChanged(propertyName)
    │      │                    └─ ErrorsChanged?.Invoke(this, e)
    │      │
    │      └─ 検証OK（既存エラーあり）
    │             └─ ClearErrors(propertyName)
    │                    └─ OnErrorsChanged(propertyName)
    │                           └─ ErrorsChanged?.Invoke(this, e)
    │
    └─ _backingField = value
```

### データフロー図

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

プロパティ値変更 ───▶ ValidateProperty() ───▶ エラー状態の変化
        │                    │                       │
        │                    ▼                       ▼
        │              エラー追加/削除          OnErrorsChanged()
        │                    │                       │
        │                    ▼                       ▼
        │              HasErrors更新          ErrorsChangedイベント
        │                    │                       │
        ▼                    ▼                       ▼
DataErrorsChangedEventArgs  エラーリスト更新     UIがGetErrors()を呼び出し
(PropertyName)                                   エラー表示を更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| INotifyDataErrorInfo.cs | `src/libraries/System.ObjectModel/src/System/ComponentModel/INotifyDataErrorInfo.cs` | ソース | インターフェース定義 |
| DataErrorsChangedEventArgs.cs | `src/libraries/System.ObjectModel/src/System/ComponentModel/DataErrorsChangedEventArgs.cs` | ソース | イベント引数クラス |
| INotifyPropertyChanged.cs | `src/libraries/System.ObjectModel/src/System/ComponentModel/INotifyPropertyChanged.cs` | ソース | 関連インターフェース（データバインディング） |
