From e970507404fcd5ac46fc55682eb764bbb67c2fe0 Mon Sep 17 00:00:00 2001
From: Kazuki Ota <117221407+kaota_microsoft@users.noreply.github.com>
Date: Thu, 2 Jul 2026 14:25:46 +0900
Subject: [PATCH 1/2] Proofread English docs and add Japanese docs
- Improve English wording across docs/docs Markdown pages.
- Add mirrored Japanese Markdown translations under docs/docs-ja.
- Keep VuePress configuration and npm scripts unchanged.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---
docs/docs-ja/README.md | 126 ++++
docs/docs-ja/advanced/awaitable.md | 63 ++
docs/docs-ja/advanced/r3-migration.md | 189 ++++++
docs/docs-ja/advanced/thread.md | 91 +++
.../advanced/work-with-other-mvvm-framwork.md | 141 ++++
docs/docs-ja/features/Collections.md | 511 +++++++++++++++
docs/docs-ja/features/Commanding.md | 501 ++++++++++++++
.../Event-transfer-to-ViewModel-from-View.md | 169 +++++
docs/docs-ja/features/Extension-methods.md | 364 +++++++++++
docs/docs-ja/features/Notifiers.md | 272 ++++++++
docs/docs-ja/features/ReactiveProperty.md | 614 ++++++++++++++++++
docs/docs-ja/features/ReactivePropertySlim.md | 124 ++++
...together-with-plane-model-layer-objects.md | 251 +++++++
docs/docs-ja/getting-started/add-snippets.md | 43 ++
docs/docs-ja/getting-started/avalonia.md | 62 ++
docs/docs-ja/getting-started/blazor.md | 126 ++++
docs/docs-ja/getting-started/uno-platform.md | 134 ++++
docs/docs-ja/getting-started/uwp.md | 92 +++
docs/docs-ja/getting-started/wpf.md | 99 +++
docs/docs-ja/getting-started/xf.md | 65 ++
docs/docs-ja/samples.md | 15 +
docs/docs/README.md | 38 +-
docs/docs/advanced/awaitable.md | 12 +-
docs/docs/advanced/r3-migration.md | 6 +-
docs/docs/advanced/thread.md | 26 +-
.../advanced/work-with-other-mvvm-framwork.md | 30 +-
docs/docs/features/Collections.md | 54 +-
docs/docs/features/Commanding.md | 82 +--
.../Event-transfer-to-ViewModel-from-View.md | 20 +-
docs/docs/features/Extension-methods.md | 35 +-
docs/docs/features/Notifiers.md | 46 +-
docs/docs/features/ReactiveProperty.md | 138 ++--
docs/docs/features/ReactivePropertySlim.md | 18 +-
...together-with-plane-model-layer-objects.md | 32 +-
docs/docs/getting-started/add-snippets.md | 4 +-
docs/docs/getting-started/avalonia.md | 22 +-
docs/docs/getting-started/blazor.md | 36 +-
docs/docs/getting-started/uno-platform.md | 23 +-
docs/docs/getting-started/uwp.md | 12 +-
docs/docs/getting-started/wpf.md | 18 +-
docs/docs/getting-started/xf.md | 23 +-
docs/docs/samples.md | 10 +-
42 files changed, 4390 insertions(+), 347 deletions(-)
create mode 100644 docs/docs-ja/README.md
create mode 100644 docs/docs-ja/advanced/awaitable.md
create mode 100644 docs/docs-ja/advanced/r3-migration.md
create mode 100644 docs/docs-ja/advanced/thread.md
create mode 100644 docs/docs-ja/advanced/work-with-other-mvvm-framwork.md
create mode 100644 docs/docs-ja/features/Collections.md
create mode 100644 docs/docs-ja/features/Commanding.md
create mode 100644 docs/docs-ja/features/Event-transfer-to-ViewModel-from-View.md
create mode 100644 docs/docs-ja/features/Extension-methods.md
create mode 100644 docs/docs-ja/features/Notifiers.md
create mode 100644 docs/docs-ja/features/ReactiveProperty.md
create mode 100644 docs/docs-ja/features/ReactivePropertySlim.md
create mode 100644 docs/docs-ja/features/Work-together-with-plane-model-layer-objects.md
create mode 100644 docs/docs-ja/getting-started/add-snippets.md
create mode 100644 docs/docs-ja/getting-started/avalonia.md
create mode 100644 docs/docs-ja/getting-started/blazor.md
create mode 100644 docs/docs-ja/getting-started/uno-platform.md
create mode 100644 docs/docs-ja/getting-started/uwp.md
create mode 100644 docs/docs-ja/getting-started/wpf.md
create mode 100644 docs/docs-ja/getting-started/xf.md
create mode 100644 docs/docs-ja/samples.md
diff --git a/docs/docs-ja/README.md b/docs/docs-ja/README.md
new file mode 100644
index 00000000..9b44bf8a
--- /dev/null
+++ b/docs/docs-ja/README.md
@@ -0,0 +1,126 @@
+# ReactiveProperty とは
+
+ReactiveProperty は Reactive Extensions 向けに MVVM と非同期処理を支援する機能を提供します。ターゲット フレームワークは .NET Standard 2.0 です。
+
+
+
+ReactiveProperty のコンセプトは 楽しいプログラミング です。
+ReactiveProperty を使うと MVVM アプリケーションを記述できます。とても楽しいですよ!
+
+
+
+次のコードは、ReactiveProperty と通常のオブジェクト プロパティの間の双方向バインディングを示しています。
+
+```csharp
+class Model : INotifyPropertyChanged
+{
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ private string _name;
+ public string Name
+ {
+ get => _name;
+ set
+ {
+ _name = value;
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
+ }
+ }
+}
+class ViewModel
+{
+ private readonly Model _model = new Model();
+ public ReactiveProperty Name { get; }
+ public ViewModel()
+ {
+ // ReactiveProperty と Model#Name プロパティの双方向同期。
+ Name = _model.ToReactivePropertyAsSynchronized(x => x.Name);
+ }
+}
+```
+
+ReactiveProperty は `IObservable` を通じて実装されています。そうです!LINQ を使えます。
+
+```csharp
+var name = new ReactiveProperty();
+name.Where(x => x.StartsWith("_")) // フィルター
+ .Select(x => x.ToUpper()) // 変換
+ .Subscribe(x => { ... 何らかの処理 ... });
+```
+
+ReactiveProperty は `IObservable` から作成されます。
+
+```csharp
+class ViewModel
+{
+ public ReactiveProperty Input { get; }
+ public ReactiveProperty Output { get; }
+
+ public ViewModel()
+ {
+ Input = new ReactiveProperty("");
+ Output = Input
+ .Delay(TimeSpan.FromSeconds(1)) // Rx メソッドを使用。
+ .Select(x => x.ToUpper()) // LINQ メソッドを使用。
+ .ToReactiveProperty(); // ReactiveProperty に変換
+ }
+}
+```
+
+このメソッド チェーンはとてもクールです。
+
+`ICommand` と `IObservable` インターフェイスを実装する `ReactiveCommand` クラスも提供しています。`ReactiveCommand` は `IObservable` から作成できます。
+次のサンプルでは、`Input` プロパティが空でないときに実行できる `ReactiveCommand` を作成します。
+
+```csharp
+class ViewModel
+{
+ public ReactiveProperty Input { get; }
+ public ReactiveProperty Output { get; }
+
+ public ReactiveCommand ResetCommand { get; }
+
+ public ViewModel()
+ {
+ Input = new ReactiveProperty("");
+ // 上のサンプルと同じ
+ Output = Input
+ .Delay(TimeSpan.FromSeconds(1)) // Rx メソッドを使用。
+ .Select(x => x.ToUpper()) // LINQ メソッドを使用。
+ .ToReactiveProperty(); // ReactiveProperty に変換
+
+ ResetCommand = Input.Select(x => !string.IsNullOrWhiteSpace(x)) // ReactiveProperty を IObservable に変換
+ .ToReactiveCommand() // IObservable から ReactiveCommand を作成できます。true 値が発行されると、コマンドを実行できます。
+ .WithSubscribe(() => Input.Value = ""); // ResetCommand.Subscribe(() => ...) のショートカットです。
+ }
+}
+```
+
+クールです!本当に宣言的で分かりやすいです。
+
+## 始めましょう!
+
+ReactiveProperty は次のリンクから使い始めることができます。
+
+- [Windows Presentation Foundation](getting-started/wpf.md)
+- [Universal Windows Platform](getting-started/uwp.md)
+- [Xamarin.Forms](getting-started/xf.md)
+- [Uno Platform](getting-started/uno-platform.md)
+
+コア機能については、次のリンクで学べます。
+
+- [ReactiveProperty](features/ReactiveProperty.md)
+- [コマンド](features/Commanding.md)
+- [コレクション](features/Collections.md)
+
+
+## NuGet パッケージ
+
+|パッケージ ID|バージョンとダウンロード数|説明|
+|----|----|----|
+|ReactiveProperty||すべてのコア機能が含まれ、ターゲット プラットフォームは .NET Standard 2.0 です。ほぼすべての状況に適しています。|
+|ReactiveProperty.Core||`ReactivePropertySlim` や `ReadOnlyReactivePropertySlim` など、最小限のクラスが含まれます。System.Reactive にも依存しません。Rx 機能が不要な場合に適しています。|
+|ReactiveProperty.WPF||WPF 向けの EventToReactiveProperty と EventToReactiveCommand が含まれます。.NET Core 3.0 以降および .NET Framework 4.7.2 以降向けです。|
+|ReactiveProperty.UWP||UWP 向けの EventToReactiveProperty と EventToReactiveCommand が含まれます。|
+|ReactiveProperty.XamarinAndroid||Xamarin.Android ネイティブのイベントから IObservable インスタンスを作成するための多くの拡張メソッドが含まれます。|
+|ReactiveProperty.XamariniOS||ReactiveProperty と ReactiveCommand を Xamarin.iOS ネイティブ コントロールにバインドするための多くの拡張メソッドが含まれます。|
\ No newline at end of file
diff --git a/docs/docs-ja/advanced/awaitable.md b/docs/docs-ja/advanced/awaitable.md
new file mode 100644
index 00000000..931098ea
--- /dev/null
+++ b/docs/docs-ja/advanced/awaitable.md
@@ -0,0 +1,63 @@
+# Awaitable
+
+`ReactiveProperty`(`ReactivePropertySlim` を含む)、`ReadOnlyReactiveProperty`(`ReadOnlyReactivePropertySlim` を含む)、`ReactiveCommand` では `await` 演算子を使用できます。
+`await` 演算子を使用すると、次の値が発行されるまでプログラムは待機します。
+
+## 例:
+
+```csharp
+// CancellationTokenSource を持つ View
+public partial class SampleWindow : Window
+{
+ CancellationTokenSource cts;
+ SampleViewModel viewModel;
+
+ public SampleWindow()
+ {
+ InitializeComponent();
+ cts = new CancellationTokenSource();
+ viewModel = new SampleViewModel(cts.Token);
+ }
+
+ protected override void OnClosed(EventArgs e)
+ {
+ // 終了時に、すべての await をキャンセルします。
+ cts.Cancel();
+ cts.Dispose();
+
+ base.OnClosed(e);
+ }
+}
+
+// CancellationToken を持つ ViewModel
+public class SampleViewModel
+{
+ public ReactiveCommand MyCommand { get; private set; }
+ public ReactiveProperty ClickCount { get; private set; }
+
+ public SampleViewModel(CancellationToken closeToken)
+ {
+ MyCommand = new ReactiveCommand();
+ ClickCount = new ReactiveProperty();
+
+ // async/await でイベントを処理します。
+ SubscribeAsync(closeToken);
+ }
+
+ async void SubscribeAsync(CancellationToken closeToken)
+ {
+ using (var handler = MyCommand.GetAsyncHandler(closeToken))
+ {
+ while (true)
+ {
+ await handler; // クリックされるまで await します。
+ ClickCount.Value += 1;
+ }
+ }
+ }
+}
+```
+
+複数回 await する場合は、`GetAsyncHandler` から `ObservableAsyncHandler` を取得してください。これは割り当てなしで複数回 await できます。1 回だけ await する場合は、`await command.WaitUntilValueChangedAsync(token)` を使用できます。
+
+> 注: `ReactiveProperty` を直接 await することもできますが、`GetAsyncHandler`(複数回の await)または `WaitUntilValueChangedAsync`(1 回限り)を使用し、`CancellationToken` を渡すことを推奨します。
diff --git a/docs/docs-ja/advanced/r3-migration.md b/docs/docs-ja/advanced/r3-migration.md
new file mode 100644
index 00000000..b86d1b0a
--- /dev/null
+++ b/docs/docs-ja/advanced/r3-migration.md
@@ -0,0 +1,189 @@
+# ReactiveProperty.R3 で R3 に移行する
+
+ReactiveProperty では新規アプリケーションに [R3](https://github.com/Cysharp/R3) を推奨するようになりましたが、既存アプリの多くは R3 が標準では提供しない機能にまだ依存しています。`ReactiveProperty.R3` は、そのようなケースのための永続的なブリッジ パッケージです。使い慣れた ReactiveProperty の体験を保ちながら、R3 と相性のよい Observable を公開し、`System.Reactive` のスケジューラーではなく `TimeProvider` / `SynchronizationContext` を使用します。
+
+## 使用する場面
+
+プロジェクトを `Reactive.Bindings` から R3 へ移行していて、R3 が意図的に含めていない上位レベルの MVVM ヘルパーがまだ必要な場合は、`ReactiveProperty.R3` を使用します。
+
+このブリッジは、移行中によく現れる次の不足を補います:
+
+- `BooleanNotifier`、`BusyNotifier`、`CountNotifier`、`ScheduledNotifier` などの notifier とメッセージ ブローカー
+- `ReactiveTimer`
+- `AsyncReactiveCommand`
+- `ReadOnlyReactiveCollection` とコレクション ヘルパー
+- `ValidatableReactiveProperty` と検証ヘルパー
+- `ToReactivePropertyAsSynchronized`
+
+## パッケージをインストールする
+
+> **ブリッジの提供状況:** `R3` と `ObservableCollections.R3` はすでに NuGet で利用できます。
+> `ReactiveProperty.R3` と `ReactiveProperty.R3.WPF` のブリッジ パッケージは **まだ公開されていません**。
+> 公開されるまでは、このリポジトリの `Source/ReactiveProperty.R3` と
+> `Source/ReactiveProperty.R3.WPF` プロジェクトに `ProjectReference` を追加して、ソースからブリッジを参照してください。
+> 以下の `dotnet add package` コマンドは、ブリッジのリリース後に想定している利用手順を示しています。
+
+.NET CLI または Visual Studio NuGet Package Manager を使用して、プロジェクトにパッケージを追加します。
+
+.NET CLI を使用している場合は、次を実行します:
+
+```powershell
+dotnet add package R3
+dotnet add package ReactiveProperty.R3
+```
+
+Visual Studio を使用している場合は、プロジェクトを右クリックし、Manage NuGet Packages を選択して `R3` と `ReactiveProperty.R3` を検索し、そこからインストールします。
+
+プロジェクトで WPF のトリガー アクションまたはコンバーターを使用している場合は、WPF ブリッジ パッケージも追加します:
+
+```powershell
+dotnet add package ReactiveProperty.R3.WPF
+```
+
+Visual Studio ユーザーは、同じ方法で NuGet Package Manager から `ReactiveProperty.R3.WPF` をインストールできます。
+
+## 移行の進め方
+
+1. 古い ReactiveProperty パッケージを `R3` と `ReactiveProperty.R3` に置き換えます。
+2. R3 がすでに直接提供している部分は、ネイティブの R3 API に書き換えます。
+3. ブリッジ型は、上記の本当の不足部分にだけ残します。
+4. Observable を合成するファイルでは `using R3;` を追加します。ブリッジ型は R3 Observable を返すためです。
+
+### 名前空間の変更
+
+このブリッジは専用の名前空間を使用するため、段階的な移行中に元の ReactiveProperty パッケージと共存できます:
+
+- `Reactive.Bindings` -> 直接変換では `R3`
+- `Reactive.Bindings.Extensions` -> `R3` と `Reactive.Bindings.R3.Extensions`
+- `Reactive.Bindings.Notifiers` -> `Reactive.Bindings.R3.Notifiers`
+
+次の表は、もっとも一般的な移行を示しています:
+
+| ReactiveProperty API | R3 / ブリッジでの置き換え |
+|---|---|
+| `ReactivePropertySlim` | `R3.ReactiveProperty` |
+| `AsyncReactiveCommand` | `Reactive.Bindings.R3.AsyncReactiveCommand` |
+| `BusyNotifier` | `Reactive.Bindings.R3.Notifiers.BusyNotifier` |
+| `ReadOnlyReactiveCollection` | `Reactive.Bindings.R3.ReadOnlyReactiveCollection` |
+| `ValidatableReactiveProperty` | `Reactive.Bindings.R3.ValidatableReactiveProperty` |
+| `ToReactivePropertyAsSynchronized` | `Reactive.Bindings.R3.Extensions.ToReactivePropertyAsSynchronized` |
+
+典型的な移行後のコードは次のようになります:
+
+```csharp
+using R3;
+using Reactive.Bindings.R3.Notifiers;
+
+public sealed class ViewModel
+{
+ public ReactiveProperty Count { get; } = new(0);
+ public BusyNotifier IsBusy { get; } = new();
+}
+```
+
+## 実行可能なサンプル
+
+このリポジトリには、完全な移行を文脈付きで並べて確認できる WPF アプリの **移行前/移行後ペア** が含まれています:
+
+- **移行前** — `Samples/ReactivePropertySamples.WPF`(`Samples/ReactivePropertySamples.Shared` を含む):
+ `Reactive.Bindings`(ReactiveProperty)を基にした元のアプリです。
+- **移行後** — `Samples/ReactivePropertySamples.R3.WPF`(`Samples/ReactivePropertySamples.R3.Shared` を含む):
+ 同じアプリを R3 + `ReactiveProperty.R3` に移行したものです。
+
+ViewModel は `.Shared` プロジェクトにあるため、2 つの `.Shared` フォルダーを比較すると、どのシンボルがどのように変わったかを正確に確認できます。移行後の ViewModel は `Samples/ReactivePropertySamples.R3.Tests` でもカバーされており、以下で説明する動作を固定しています。
+
+## GitHub Copilot CLI で移行する
+
+このリポジトリには、`skills/migrating-reactiveproperty-to-r3/` に移行用の **skill** が含まれています。これは上記の手順を、繰り返し実行できるエージェント駆動のフローにします。パッケージ参照を変更し、マッピング テーブルに基づいてすべての ReactiveProperty シンボルを書き換え、推測ではなく人の判断が必要な少数のケースを報告します。以下のフローは、ViewModel、DataAnnotations 検証、notifier、`ReadOnlyReactiveCollection`、XAML の `EventToReactiveCommand` を使用するサンプル WPF アプリでエンドツーエンドに検証済みです。
+
+### 1. skill をインストールする
+
+**推奨 — CLI が自動的に読み込み、エージェントが skill のマッピング テーブルをスムーズに読めるように、あなたのプロジェクトにインストールしてください。** skill フォルダーをプロジェクトの `.agents/skills/` ディレクトリにコピーします(これはリポジトリの `skills/README.md` が最初に推奨している方法です):
+
+```powershell
+# このリポジトリのクローンから、あなたのアプリのリポジトリ ルートで実行します
+Copy-Item -Recurse /skills/migrating-reactiveproperty-to-r3 `
+ ".agents/skills/migrating-reactiveproperty-to-r3"
+```
+
+skill がプロジェクト ツリーの **内側** にあるため、エージェントは同梱の `references/rules.json` を構造化ファイル リーダーで直接読み取れます — 読み取りスコープの回避策は不要です。
+
+**代替 — 個人用 Copilot skills ディレクトリに一度だけインストールし、すべてのプロジェクトで使用します**:
+
+```powershell
+Copy-Item -Recurse skills/migrating-reactiveproperty-to-r3 `
+ "$HOME/.copilot/skills/migrating-reactiveproperty-to-r3"
+```
+
+macOS/Linux での個人用のコピー先は `~/.copilot/skills/migrating-reactiveproperty-to-r3` です。複数のプロジェクトを移行するときに便利ですが、その場合 skill フォルダーはプロジェクトの *外側* に置かれるため、このガイドの最後にある読み取りスコープに関する注意に該当します。どちらの方法でも、コピー後にプロジェクト内で `copilot` を起動します。skill は自動的に読み込まれ、R3 への移行を依頼したときに有効になります。(ローカル プラグインや marketplace としてインストールする方法も使えますが、フォルダーをコピーするのがもっとも簡単です。)
+
+### 2. コードを変更する前に計画を依頼する
+
+プロジェクトで CLI を開き、まず棚卸しと計画を依頼します。スコープを絞った現実的なプロンプトが最適です — エージェントに「すべてを移行して」と一度に依頼しないでください:
+
+```text
+この WPF アプリを ReactiveProperty から R3 に移行したいです。コードを変更する前に、
+プロジェクト内のすべての ReactiveProperty シンボルを棚卸しし、それぞれについて、
+一致するルール、対象 (r3-direct / reactiveproperty-r3 / manualReview)、R3 での置き換えを
+教えてください。manual-review 項目は別に一覧化してください。
+```
+
+エージェントはマッピング テーブルを読み取り、シンボルごとの計画を作成します。そこには、直接の R3 置き換え(`ReactivePropertySlim` → `R3.ReactiveProperty`、`ReactiveProperty` → `R3.BindableReactiveProperty`、`ObserveProperty` → `ObservePropertyChanged`、…)、本当の不足部分に対するブリッジ置き換え(`AsyncReactiveCommand`、`BusyNotifier`、`ReadOnlyReactiveCollection`、`ValidatableReactiveProperty`、`ToReactivePropertyAsSynchronized`)、短い manual-review リストが含まれます。
+
+### 3. 段階的に移行する
+
+小さくレビューしやすい単位で移行し、同じセッションを `--continue` で継続します:
+
+```text
+CounterViewModel と PeopleViewModel を今 R3 に移行してください。NuGet の R3 と、
+不足する型には ReactiveProperty.R3 ブリッジを使用してください。
+```
+
+```text
+次に残りの ViewModel を移行し、パッケージ参照と using ディレクティブを修正し、
+XAML の EventToReactiveCommand xmlns を R3.WPF ブリッジに差し替えてください。
+```
+
+XAML トリガー アクションの場合、書き換えはほぼ xmlns の差し替えです:
+
+```xml
+
+xmlns:i="clr-namespace:Reactive.Bindings.Interactivity;assembly=ReactiveProperty.WPF"
+
+xmlns:i="clr-namespace:Reactive.Bindings.R3.Interactivity;assembly=ReactiveProperty.R3.WPF"
+```
+
+### 4. ビルド、テスト、修正する
+
+エージェントに既存のテストのビルドと実行を依頼し、失敗があれば具体的なプロンプトで対応します:
+
+```text
+ソリューションをビルドしてテストを実行し、ビルド状態、テスト状態、manual-review
+リストを報告してください。
+```
+
+```text
+ビルドが次のエラーで失敗します: <エラーを貼り付ける>。修正してください。
+```
+
+ブリッジの不足部分を補う型は **R3** Observable を公開するため、購読や演算子チェーン(`Subscribe`、`Where`、`Select`、…)を使うファイルには `using R3;` が存在することを確認してください。
+
+> **検証タイミング:** 単一プロパティの DataAnnotations は R3 の
+> `BindableReactiveProperty.EnableValidation()` に対応しますが、R3 の検証は **遅延実行** です — バインディングまたは購読者がアタッチされるまで初期値をエラーとして扱いません。ヘッドレス テスト(またはロジック)が元の即時検証を期待している場合は、代わりに `ReactiveProperty.R3` の `ValidatableReactiveProperty` を使用してください。これは即時に検証します。
+
+### 5. manual-review 項目を解決する
+
+skill は機械的に書き換えられないケースを推測しません。ファイル、行、メモ付きでフラグを立てます。通常は次のような短いリストになります:
+
+- **`ReactivePropertyMode` 引数**(たとえば `ToReactivePropertyAsSynchronized` や `ReactiveProperty` コンストラクター上のもの)。R3 に対応するものはないため、エージェントはそれを削除し、意図を再現する方法を説明します。`DistinctUntilChanged` は R3 の既定の重複除外動作に対応し、`RaiseLatestValueOnSubscribe` はプロパティが現在値を再生するかどうかに対応します。実際に依存していた動作を確認してください。
+- **カスタム `IScheduler` 引数。** R3 は時間に `TimeProvider`、ディスパッチに `SynchronizationContext` を使用するため、既定以外のスケジューラーは自動変換できません。エージェントはそれを報告し、あなたがその呼び出し箇所に適した provider を選択します。
+- **`System.Reactive` に残す必要がある `System.IObservable` 境界**(公開 API、サードパーティの Rx など)。宣言を書き換えるのではなく、R3 の `ToObservable()` / `AsSystemObservable()` でブリッジしてください。
+- **即時検証のままにする必要がある DataAnnotations 検証。** skill は単一プロパティの DataAnnotations を `EnableValidation()` に書き換えますが、これは遅延検証です — 上記の **検証タイミング** の注を参照してください。即時検証に依存していた場合(たとえばヘッドレス テストなど)は、そのプロパティを `ValidatableReactiveProperty` に切り替えてください。
+
+このフロー全体は、「このアプリを R3 に移行して」「ReactiveProperty を R3 に置き換えて」「この ViewModel を ReactiveProperty から移行して」のような簡単な依頼で開始できます。
+
+> **注 (個人用 `~/.copilot/skills/` インストールを使用した場合のみ):** skill は、同梱のマッピング テーブル `migrating-reactiveproperty-to-r3/references/rules.json` によって動作します。CLI の構造化ファイル リーダーはプロジェクト ディレクトリにスコープされるため、skill がプロジェクトの外側にある `~/.copilot/skills/` 配下にある場合、エージェントがそのファイルを「読めない」と報告することがあります — コンテンツ/ポリシー ブロックだと誤って表示することさえあります。これは読み取りスコープ上の癖であり、実際のブロックではありません。エージェントは引き続き(たとえばシェル コマンドで)読み取ることができ、そうでない場合も skill 自体に含まれるガイダンスにフォールバックします。**step 1 で推奨しているように、skill をプロジェクトの `.agents/skills/` にインストールすれば、この問題は完全に避けられます**。マッピング テーブルが作業ツリーの内側に置かれるためです。
+
+## 大規模な移行に関するメモ
+
+このブリッジは一時的な shim ではなく、長期的な移行パスとして意図されています。既存の MVVM パターンやすでに依存している動作を保ちながら、段階的に R3 へ移行したいプロジェクトに適しています。
diff --git a/docs/docs-ja/advanced/thread.md b/docs/docs-ja/advanced/thread.md
new file mode 100644
index 00000000..c8c2a23b
--- /dev/null
+++ b/docs/docs-ja/advanced/thread.md
@@ -0,0 +1,91 @@
+# スレッド
+
+ReactiveProperty は実行スレッドを制御する機能を提供します。
+ReactiveProperty は `PropertyChanged` イベントを UI スレッドで自動的に発生させます。
+
+## スケジューラーを変更する
+
+この動作は `IScheduler` を使って変更できます。
+インスタンスを作成するときに、`raiseEventScheduler` 引数に `IScheduler` インスタンスを設定します。
+
+```csharp
+var rp = Observable.Interval(TimeSpan.FromSeconds(1))
+ .ToReactiveProperty(raiseEventScheduler: ImmediateScheduler.Instance);
+```
+
+`ReactiveCollection` と `ReadOnlyReactiveCollection` は、`ReactiveProperty` と同様に UI スレッドで `CollectionChanged` イベントを発生させます。
+この動作は、コンストラクターやファクトリー メソッドの scheduler 引数を使用して変更できます。
+
+```csharp
+var collection = Observable.Interval(TimeSpan.FromSeconds(1))
+ .ToReactiveCollection(scheduler: ImmediateScheduler.Instance);
+
+var readOnlyCollection = Observable.Interval(TimeSpan.FromSeconds(1))
+ .ToReadOnlyReactiveProperty(scheduler: ImmediateScheduler.Instance);
+```
+
+## グローバル スケジューラーを変更する
+
+`ReactivePropertyScheduler.SetDefault` メソッドを使用すると、ReactiveProperty の既定のスケジューラーを変更できます。
+
+```csharp
+ReactivePropertyScheduler.SetDefault(TaskPoolScheduler.Default);
+var taskPoolRp = new ReactiveProperty();
+ReactivePropertyScheduler.SetDefault(ImmediateScheduler.Instance);
+var immediateRp = new ReactiveProperty();
+
+taskPoolRp.Value = "changed"; // TaskPoolScheduler スレッドでイベントを発生させます。
+immediateRp.Value = "changed"; // ImmediateScheduler スレッドでイベントを発生させます。
+```
+
+## グローバル スケジューラー ファクトリーを変更する
+
+`ReactivePropertyScheduler.SetDefaultSchedulerFactory` メソッドを使用すると、ReactiveProperty の既定のスケジューラー インスタンスを作成するファクトリー メソッドを変更できます。
+
+```csharp
+using System.Reactive.Concurrency;
+using System.Windows;
+using System.Windows.Threading;
+using Reactive.Bindings;
+
+namespace MultiUIThreadApp
+{
+ public partial class App : Application
+ {
+ private void Application_Startup(object sender, StartupEventArgs e)
+ {
+ // 各インスタンスの作成時に DispatcherScheduler インスタンスを作成するように設定します
+ // 対象は ReactiveProperty、ReadOnlyReactiveProperty、ReactiveCollection、ReadOnlyReactiveProperty です。
+ ReactivePropertyScheduler.SetDefaultSchedulerFactory(() =>
+ new DispatcherScheduler(Dispatcher.CurrentDispatcher));
+ }
+ }
+}
+```
+
+## Rx オペレーター
+
+もちろん、`ObserveOn` 拡張メソッドを使用できます。
+
+```csharp
+var rp = Observable.Interval(TimeSpan.FromSeconds(1))
+ .ObserveOn(someScheduler)
+ .ToReactiveProperty();
+```
+
+`ObserveOnUIDispatcher` 拡張メソッドも提供しています。
+これは `ObserveOn(ReactivePropertyScheduler.Default)` のショートカットです。
+
+```csharp
+var rp = Observable.Interval(TimeSpan.FromSeconds(1))
+ .ObserveOnUIDispatcher()
+ .ToReactiveProperty();
+```
+
+## 注意
+
+既定では、ReactiveProperty は単一 UI スレッドのプラットフォーム向けに設計されています。
+つまり、UWP などの複数 UI スレッドを持つプラットフォームでは、一部の機能が動作しません。
+
+UWP では、複数のウィンドウを作成すると、単一プロセス内に複数の UI スレッドが存在します。
+UWP で複数のウィンドウを作成する場合は、`ReactivePropertyScheduler.SetDefault` メソッドで `ImmediateScheduler` を設定して UI スレッドへの自動イベント ディスパッチを無効にするか、`ReactivePropertyScheduler.SetDefaultSchedulerFactory` メソッドを使用して UI スレッドごとに異なるスケジューラー インスタンスを作成してください。または、ReactiveProperty / ReadOnlyReactiveProperty クラスの代わりに `ReactivePropertySlim` / `ReadOnlyReactivePropertySlim` クラスを使用してください。
diff --git a/docs/docs-ja/advanced/work-with-other-mvvm-framwork.md b/docs/docs-ja/advanced/work-with-other-mvvm-framwork.md
new file mode 100644
index 00000000..fcd88796
--- /dev/null
+++ b/docs/docs-ja/advanced/work-with-other-mvvm-framwork.md
@@ -0,0 +1,141 @@
+# 他の MVVM フレームワークと連携する
+
+ReactiveProperty は ViewModel やその他のレイヤー向けの基底クラスを提供しません。
+つまり、Prism、MVVM Light Toolkit などの他の MVVM フレームワークと一緒に ReactiveProperty を使用できます。
+
+このセクションでは、ReactiveProperty を Prism と一緒に使う方法を説明します。
+
+始めましょう!
+
+## Prism プロジェクトを作成する
+
+Prism は Visual Studio 向けに Prism Template Pack 拡張機能を提供しています。
+拡張機能をインストールすると、プロジェクト テンプレートからアプリを作成できます。
+
+
+
+ReactiveProperty を Prism と一緒に使用する場合、`DelegateCommand` を `ReactiveCommand` に置き換えられます。また、その他すべての ReactiveProperty 機能も Prism と一緒に使用できます。
+
+この例では、PrismSampleApp という名前の Prism Blank App (WPF) と、PrismSampleModule という名前の Prism Module (WPF) を作成します。
+PrismSampleApp に PrismSampleModule への参照を追加し、次に以下のように App.xaml.cs を編集してモジュールを追加します:
+
+```csharp
+public partial class App
+{
+ protected override Window CreateShell()
+ {
+ return Container.Resolve();
+ }
+
+ protected override void RegisterTypes(IContainerRegistry containerRegistry)
+ {
+
+ }
+
+ protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
+ {
+ moduleCatalog.AddModule();
+ }
+}
+```
+
+次に、PrismSampleModuleModule.cs を編集してナビゲーション用のビューを追加し、ViewA をシェルに登録します。
+
+```csharp
+using PrismSampleModule.Views;
+using Prism.Ioc;
+using Prism.Modularity;
+using Prism.Regions;
+
+namespace PrismSampleModule
+{
+ public class PrismSampleModuleModule : IModule
+ {
+ private readonly IRegionManager _regionManager;
+
+ public PrismSampleModuleModule(IRegionManager regionManager)
+ {
+ _regionManager = regionManager;
+ }
+
+ public void OnInitialized(IContainerProvider containerProvider)
+ {
+ _regionManager.RequestNavigate("ContentRegion", "ViewA");
+ }
+
+ public void RegisterTypes(IContainerRegistry containerRegistry)
+ {
+ containerRegistry.RegisterForNavigation();
+ }
+ }
+}
+```
+
+## ReactiveProperty を使用する
+
+NuGet を使用して、すべてのプロジェクトに ReactiveProperty 参照を追加します。ReactiveProperty の任意のクラスを自由に使用できます。
+
+この例では、以下に示すように ViewAViewModel.cs で ReactiveProperty の機能を使用します:
+
+```csharp
+using Prism.Mvvm;
+using Reactive.Bindings;
+using System;
+using System.Linq;
+using System.Reactive.Linq;
+
+namespace PrismSampleModule.ViewModels
+{
+ public class ViewAViewModel : BindableBase
+ {
+ public ReactiveProperty Input { get; }
+ public ReadOnlyReactiveProperty Output { get; }
+
+ public ReactiveCommand ResetCommand { get; }
+
+ public ViewAViewModel()
+ {
+ Input = new ReactiveProperty("");
+ Output = Input.Delay(TimeSpan.FromSeconds(1))
+ .Select(x => x.ToUpper())
+ .ToReadOnlyReactiveProperty();
+
+ ResetCommand = Input.Select(x => !string.IsNullOrWhiteSpace(x))
+ .ToReactiveCommand()
+ .WithSubscribe(() => Input.Value = "");
+ }
+ }
+}
+```
+
+次に、`ViewA.xaml` を編集します。
+
+```xml
+
+
+
+
+
+
+
+```
+
+問題なく動作します。:)
+
+
+
+## まとめ
+
+ReactiveProperty は基底クラスを提供しません。
+このセクションで説明したように、ReactiveProperty は他の MVVM フレームワークと一緒に使用できます。
diff --git a/docs/docs-ja/features/Collections.md b/docs/docs-ja/features/Collections.md
new file mode 100644
index 00000000..c9c216d3
--- /dev/null
+++ b/docs/docs-ja/features/Collections.md
@@ -0,0 +1,511 @@
+# コレクション
+
+ReactiveProperty はいくつかのコレクション クラスを提供します。
+
+- ReactiveCollection<T>
+- ReadOnlyReactiveCollection<T>
+- IFilteredReadOnlyObservableCollection<T>
+
+## ReactiveCollection
+
+`ReactiveCollection` は `ObservableCollection` を継承しています。
+このクラスは `IObservable` から作成されます。
+元の `IObservable` から値が通知されると、項目を追加します。
+`ReactiveCollection` はこの処理を `IScheduler` を使って実行します。既定の `IScheduler` は UI スレッドへディスパッチします。
+
+```csharp
+public class ViewModel
+{
+ public ReactiveCollection Records { get; }
+
+ public ReactiveCommand StartRecordCommand { get; }
+
+ public ViewModel()
+ {
+ StartRecordCommand = new ReactiveCommand();
+ // IObservable から ReactiveCollection インスタンスを作成します
+ Records = StartRecordCommand
+ .ToUnit()
+ .Take(1)
+ .Concat(Observable.Defer(() => Observable.Interval(TimeSpan.FromSeconds(1)).ToUnit()))
+ .Select(_ => DateTime.Now)
+ .ToReactiveCollection();
+ }
+}
+```
+
+> `ToUnit` 拡張メソッドは Reactive.Bindings.Extensions 名前空間で定義されています。
+> この拡張メソッドは `.Select(_ => Unit.Default)` と同じです。
+
+UWP の例です。
+
+MainPage.xaml.cs
+```csharp
+public sealed partial class MainPage : Page
+{
+ public ViewModel ViewModel { get; } = new ViewModel();
+ public MainPage()
+ {
+ this.InitializeComponent();
+ }
+}
+```
+
+MainPage.xaml
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+
+
+## コレクション操作
+
+`ReactiveCollection` クラスには、`AddOnScheduler`、`RemoveOnScheduler`、`ClearOnScheduler`、`GetOnScheduler` などの `XxxxOnScheduler` メソッドがあります。
+これらのメソッドは `IScheduler` 上で実行され、UI スレッド以外から呼び出せます。
+
+```csharp
+public class ViewModel
+{
+ public ReactiveCollection Records { get; }
+
+ public ReactiveCommand StartRecordCommand { get; }
+
+ public ReactiveCommand ClearCommand { get; }
+
+ public ViewModel()
+ {
+ StartRecordCommand = new ReactiveCommand();
+ // IObservable から ReactiveCollection インスタンスを作成します
+ Records = StartRecordCommand
+ .ToUnit()
+ .Take(1)
+ .Concat(Observable.Defer(() => Observable.Interval(TimeSpan.FromSeconds(1)).ToUnit()))
+ .Select(_ => DateTime.Now)
+ .ToReactiveCollection();
+
+ ClearCommand = new ReactiveCommand();
+ ClearCommand.ObserveOn(TaskPoolScheduler.Default) // 別スレッドで実行します
+ .Subscribe(_ => Records.ClearOnScheduler());
+ }
+}
+```
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+
+
+`ReactiveCollection` インスタンスを破棄すると、元の IObservable インスタンスから購読解除されます。
+
+## ReadOnlyReactiveCollection
+
+`ReadOnlyReactiveCollection` クラスは、`ObservableCollection` からの一方向同期を提供します。変換ロジックを設定し、`CollectionChanged` イベントを `IScheduler` 上でディスパッチできます。既定の `IScheduler` は UI スレッドへディスパッチします。
+
+まず POCO クラスを作成します。
+
+```csharp
+public class BindableBase : INotifyPropertyChanged
+{
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected void RaisePropertyChanged([CallerMemberName]string propertyName = null) =>
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+
+ protected void SetProperty(ref T field, T value, [CallerMemberName]string propertyName = null)
+ {
+ if (EqualityComparer.Default.Equals(field, value))
+ {
+ return;
+ }
+
+ field = value;
+ RaisePropertyChanged(propertyName);
+ }
+}
+
+public class TimerObject : BindableBase, IDisposable
+{
+ private IDisposable Disposable { get; }
+
+ private long _count;
+ public long Count
+ {
+ get { return _count; }
+ private set { SetProperty(ref _count, value); }
+ }
+
+ public TimerObject()
+ {
+ Disposable = Observable.Interval(TimeSpan.FromSeconds(1))
+ .Subscribe(_ => Count++);
+ }
+
+ public void Dispose()
+ {
+ Disposable.Dispose();
+ }
+}
+```
+
+これは `Count` プロパティを 1 秒ごとにインクリメントする単純なクラスです。
+
+ReactiveProperty を使って、このクラスを ViewModel レイヤーでラップします。
+
+```csharp
+public class TimerObjectViewModel : IDisposable
+{
+ public TimerObject Model { get; }
+
+ public ReadOnlyReactiveProperty CountMessage { get; }
+
+ public TimerObjectViewModel(TimerObject timerObject)
+ {
+ Model = timerObject;
+ CountMessage = Model.ObserveProperty(x => x.Count)
+ .Select(x => $"Count value is {x}.")
+ .ToReadOnlyReactiveProperty();
+ }
+
+ public void Dispose()
+ {
+ Model.Dispose();
+ }
+}
+```
+
+`ObservableCollection` を使って `TimerObject` インスタンスを管理します。
+View レイヤーへ `TimerObjectViewModel` インスタンスを提供するには、`ReadOnlyReactiveCollection` クラスを使います。
+`ReadOnlyReactiveCollection` インスタンスは `ToReadOnlyReactiveCollection` 拡張メソッドで作成します。
+
+```csharp
+public class ViewModel
+{
+ // TimerObject のコレクション
+ private ReactiveCollection ModelCollection { get; }
+ // TimerObjectViewModel のコレクション
+ public ReadOnlyReactiveCollection ViewModelCollection { get; }
+
+ public ReactiveCommand AddCommand { get; }
+
+ public ReactiveCommand RemoveCommand { get; }
+
+ public ViewModel()
+ {
+ AddCommand = new ReactiveCommand();
+ ModelCollection = AddCommand
+ .Select(_ => new TimerObject())
+ .ToReactiveCollection();
+ // 変換ロジックを使って ReadOnlyReactiveCollection インスタンスを作成します。
+ ViewModelCollection = ModelCollection
+ .ToReadOnlyReactiveCollection(x => new TimerObjectViewModel(x));
+
+ RemoveCommand = new ReactiveCommand()
+ .WithSubscribe(x => ModelCollection.Remove(x.Model));
+ }
+}
+```
+
+テスト用の View は次のとおりです。
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+
+
+
+`ReadOnlyReactiveCollection` からインスタンスが削除されると、`Dispose` メソッドが呼び出されます。この動作が不要な場合は、`ToReadOnlyReactiveCollection()` の `disposeElement` 引数に `false` を設定します。
+
+```csharp
+ViewModelCollection = ModelCollection
+ .ToReadOnlyReactiveCollection(x => new TimerObjectViewModel(x), disposeElement: false);
+```
+
+### `IObservable` から作成する
+
+`ReadOnlyReactiveCollection` は `ReactiveCollection` と同様に `IObservable` から作成できます。ただし、`ReadOnlyReactiveCollection` にはコレクション操作メソッドがありません。
+`ToReadOnlyReactiveCollection` 拡張メソッドには `IObservable` 型の `onReset` 引数があります。
+この引数が値を発行すると、コレクションはクリアされます。
+
+```csharp
+public class ViewModel
+{
+ public ReadOnlyReactiveCollection Messages { get; }
+
+ public ReactiveCommand ResetCommand { get; }
+
+ public ViewModel()
+ {
+ ResetCommand = new ReactiveCommand();
+ Messages = Observable.Interval(TimeSpan.FromSeconds(1))
+ .Select(_ => DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"))
+ .ToReadOnlyReactiveCollection(ResetCommand.ToUnit());
+ }
+}
+```
+
+```xml
+
+
+
+
+
+
+
+
+
+
+```
+
+`ResetCommand` が実行されると、Messages コレクションがクリアされます。
+
+
+
+## IFilteredReadOnlyObservableCollection
+
+`ObservableCollection` からリアルタイムにフィルターするコレクションです。
+`IFilteredReadOnlyObservableCollection` は、元コレクション内の項目の `PropertyChanged` イベントと `CollectionChanged` イベントを監視します。
+
+```csharp
+public class ValueHolder : INotifyPropertyChanged
+{
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ public int Id { get; set; }
+
+ private int _value;
+ public int Value
+ {
+ get => _value;
+ set
+ {
+ _value = value;
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Value)));
+ }
+ }
+
+ public ValueHolder()
+ {
+ var r = new Random();
+ Observable.Interval(TimeSpan.FromSeconds(1))
+ .ObserveOnUIDispatcher()
+ .Subscribe(_ => Value = r.Next(10));
+ }
+}
+
+public class ViewModel
+{
+ public ReactiveCollection ValuesSource { get; }
+
+ public IFilteredReadOnlyObservableCollection Values { get; }
+
+ public ReactiveCommand AddCommand { get; }
+
+ public ViewModel()
+ {
+ AddCommand = new ReactiveCommand();
+ ValuesSource = AddCommand
+ .Select(_ => new ValueHolder { Id = ValuesSource.Count })
+ .ToReactiveCollection();
+ Values = ValuesSource.ToFilteredReadOnlyObservableCollection(
+ x => x.Value > 7);
+ }
+}
+```
+
+> `ObserveOnUIDispatcher` 拡張メソッドは、現在のスレッドから UI スレッドへ切り替えます。
+
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+
+
+Value プロパティが 7 より大きいとき、Filtered Values の ListView(右側)に値を表示します。
+
+### コレクション要素の監視方法をカスタマイズする
+
+要素を更新するトリガーを CollectionChanged イベントから別のトリガーに変更したい場合は、`IObservable sourceElementStatusChanged` 引数を持つ別のオーバーロードを使ってカスタマイズできます。
+
+たとえば、コレクション内の要素のネストされたプロパティでフィルターしたい場合があります。
+
+```csharp
+// ネストされたオブジェクト プロパティを持つオブジェクト
+public class NestedPropertyObject : INotifyPropertyChanged
+{
+ // INPC 実装は省略
+
+ public string Id { get; } => Guid.NewGuid().ToString();
+ public ReactivePropertySlim NestedObject { get; } = new ReactivePropertySlim(true);
+}
+
+// --------------------
+// トリガー
+var sourceCollection = new ObservableCollection
+{
+ new NestedPropertyObject(),
+ new NestedPropertyObject(),
+ new NestedPropertyObject(),
+};
+
+var filteredCollection = sourceCollection.ToFilteredReadOnlyObservableCollection(
+ // フィルター条件のラムダ式
+ x => x.NestedObject.Value,
+ // コレクション要素の更新トリガーとなる IObservable インスタンスを作成します
+ x => x.ObserveProperty(y => NestedObject.Value)
+);
+
+Console.WriteLine(filteredCollection.Count); // 3
+// filteredCollection は NestedObject.Value プロパティ パスを監視しています。
+// そのため、次の行でフィルター条件の再評価がトリガーされます
+sourceCollection[1].NestedObject.Value = false;
+Console.WriteLine(filteredCollection.Count); // 2
+```
+
+次の 2 行は同じです。
+
+```csharp
+collection.ToFilteredReadOnlyObservableCollection(x => x.SomeProperty);
+collection.ToFilteredReadOnlyObservableCollection(x => x.SomeProperty, x => x.PropertyChangedAsObservable());
+```
diff --git a/docs/docs-ja/features/Commanding.md b/docs/docs-ja/features/Commanding.md
new file mode 100644
index 00000000..9a9cd7ec
--- /dev/null
+++ b/docs/docs-ja/features/Commanding.md
@@ -0,0 +1,501 @@
+# コマンド
+
+`ReactiveCommand` クラスは次の 2 つのインターフェイスを実装しています。
+
+- `ICommand` インターフェイス
+- `IObservable`
+
+## 基本的な使い方
+
+このクラスは、`IObservable` インスタンスから `ToReactiveCommand` 拡張メソッドを使って作成できます。
+`IObservable` インスタンスが値を発行すると、`CanExecuteChanged` イベントが発生します。
+
+常に実行可能なコマンドが必要な場合は、既定のコンストラクターを使って `ReactiveCommand` インスタンスを作成できます。
+
+```csharp
+IObservable canExecuteSource = ...;
+
+ReactiveCommand someCommand = canExecuteSource.ToReactiveCommand(); // コマンド パラメーターなしのバージョン
+ReactiveCommand hasCommandParameterCommand = canExecuteSource.ToReactiveCommand(); // コマンド パラメーターありのバージョン
+ReactiveCommand alwaysExecutableCommand = new ReactiveCommand(); // コマンド パラメーターなしで常に実行できるバージョン
+ReactiveCommand alwaysExecutableAndHasCommandParameterCommand = new ReactiveCommand(); // コマンド パラメーターありで常に実行できるバージョン
+```
+
+ファクトリ拡張メソッドの `initialValue` 引数を使って、`CanExecute` メソッドの初期戻り値を設定できます。
+既定値は `true` です。
+
+```csharp
+IObservable canExecuteSource = ...;
+
+ReactiveCommand someCommand = canExecuteSource.ToReactiveCommand(false);
+ReactiveCommand hasCommandParameterCommand = canExecuteSource.ToReactiveCommand(false);
+```
+
+`Execute` メソッドが呼び出されると、`ReactiveCommand` は `OnNext` コールバックを呼び出します。
+実行ロジックは `Subscribe` メソッドで登録できます。
+
+```csharp
+ReactiveCommand someCommand = new ReactiveCommand();
+someCommand.Subscribe(_ => { ... some logic ... }); // OnNext コールバックを設定します
+
+someCommand.Execute(); // OnNext コールバックが呼び出されます。
+```
+
+## ViewModel クラスで使う
+
+最初の例では、`ReactiveCommand` クラスだけを使います。
+
+```csharp
+public class ViewModel
+{
+ public ReactiveCommand UpdateTimeCommand { get; }
+
+ public ReactiveProperty Time { get; }
+
+ public ViewModel()
+ {
+ Time = new ReactiveProperty();
+ UpdateTimeCommand = new ReactiveCommand();
+ UpdateTimeCommand.Subscribe(_ => Time.Value = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"));
+ }
+}
+```
+
+UWP の例です。
+
+```csharp
+public sealed partial class MainPage : Page
+{
+ private ViewModel ViewModel { get; } = new ViewModel();
+ public MainPage()
+ {
+ this.InitializeComponent();
+ }
+}
+```
+
+```xml
+
+
+
+
+
+
+```
+
+
+
+## LINQ と連携する
+
+`ReactiveCommand` クラスは `IObservable` インターフェイスを実装しています。
+LINQ メソッドを使用でき、`ReactiveProperty` クラスは `IObservable` から作成できます。
+前の例のコードは次のように変更できます。
+
+```csharp
+public class ViewModel
+{
+ public ReactiveCommand UpdateTimeCommand { get; }
+
+ // Value プロパティを設定する必要がないため、ReadOnlyReactiveProperty に変更できます。
+ public ReadOnlyReactiveProperty Time { get; }
+
+ public ViewModel()
+ {
+ UpdateTimeCommand = new ReactiveCommand();
+ Time = UpdateTimeCommand
+ .Select(_ => DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"))
+ .ToReadOnlyReactiveProperty();
+ }
+}
+```
+
+## `IObservable` から作成する
+
+コマンド実行後 5 秒間は `UpdateTimeCommand` を実行できないように変更します。
+
+```csharp
+public class ViewModel
+{
+ public ReactiveCommand UpdateTimeCommand { get; }
+
+ public ReadOnlyReactiveProperty Time { get; }
+
+ public ViewModel()
+ {
+ var updateTimeTrigger = new Subject();
+ UpdateTimeCommand = Observable.Merge(
+ updateTimeTrigger.Select(_ => false),
+ updateTimeTrigger.Delay(TimeSpan.FromSeconds(5)).Select(_ => true))
+ .ToReactiveCommand();
+ Time = UpdateTimeCommand
+ .Select(_ => DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"))
+ .Do(_ => updateTimeTrigger.OnNext(Unit.Default))
+ .ToReadOnlyReactiveProperty();
+ }
+}
+```
+
+
+
+## コマンドの作成と購読を 1 文で行う
+
+LINQ メソッドを使わない場合は、コマンドの作成と購読を 1 文で行えます。
+`WithSubscribe` 拡張メソッドは購読して、`ReactiveCommand` インスタンスを返します。
+
+```csharp
+public class ViewModel
+{
+ public ReactiveCommand UpdateTimeCommand { get; }
+
+ public ReactiveProperty Time { get; }
+
+ public ViewModel()
+ {
+ Time = new ReactiveProperty();
+
+ var updateTimeTrigger = new Subject();
+ UpdateTimeCommand = Observable.Merge(
+ updateTimeTrigger.Select(_ => false),
+ updateTimeTrigger.Delay(TimeSpan.FromSeconds(5)).Select(_ => true))
+ .ToReactiveCommand()
+ .WithSubscribe(() => Time.Value = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")); // ここ
+ }
+}
+```
+
+`WithSubscribe` メソッドは単なるショートカットです。
+
+```csharp
+// WithSubscribe を使わない場合
+var command = new ReactiveCommand();
+command.Subscribe(_ => { ... some actions ... });
+
+// WithSubscribe を使う場合
+var command = new ReactiveCommand()
+ .WithSubscribe(() => { ... some actions ... });
+```
+
+LINQ メソッドを使う場合は、インスタンス化と購読を別の文に分けてください。
+
+## アクションの購読解除
+
+アクションの購読を解除する必要がある場合は、`Subscribe` メソッドが返す `IDisposable` インスタンスの `Dispose` メソッドを使います。
+
+```csharp
+var command = new ReactiveCommand();
+var subscription1 = command.Subscribe(_ => { ... some actions ... });
+var subscription2 = command.Subscribe(_ => { ... some actions ... });
+
+// 各 Subscribe メソッドの購読を解除します。
+subscription1.Dispose();
+subscription2.Dispose();
+
+// すべて購読解除します
+command.Dispose();
+```
+
+`WithSubscribe` 拡張メソッドには、`IDisposable` 引数を持つオーバーロードがあります。
+
+```csharp
+IDisposable subscription = null;
+var command = new ReactiveCommand().WithSubscribe(() => { ... some actions ... }, out subscription);
+
+// 購読解除
+subscription.Dispose();
+```
+
+`Action` 引数を持つ別のオーバーロードもあります。
+これは `CompositeDisposable` クラスと一緒に使います。
+
+```csharp
+var subscriptions = new CompositeDisposable();
+var command = new ReactiveCommand()
+ .WithSubscribe(() => { ... some actions ... }, subscriptions.Add)
+ .WithSubscribe(() => { ... some actions ... }, subscriptions.Add);
+
+// 購読解除
+subscription.Dispose();
+```
+
+別のインスタンスのイベントを購読する場合は、ViewModel のライフサイクルの最後に `ReactiveCommand` クラスの `Dispose` メソッドを呼び出してください。
+
+## ReactiveCommand の非同期版
+
+`AsyncReactiveCommand` クラスは、`ReactiveCommand` クラスの `async` 版です。
+このクラスは `async` メソッドを購読できます。async メソッドの実行中は、`CanExecute` メソッドが `false` を返します。
+そのため、async メソッドの実行中は再実行できません。
+
+`ExecuteAsync` メソッドは `Execute` メソッドの async 版です。コマンドに追加されたすべての async 処理の完了を待てます。このメソッドは単体テストや C# からコマンドを呼び出すときに便利です。
+
+### 基本的な使い方
+
+`ReactiveCommand` クラスとほぼ同じです。
+唯一の違いは、`Subscribe` メソッドの引数として `async` メソッドを受け取れることと、`IObservable` インターフェイスを実装していないことです。
+
+```csharp
+public class ViewModel
+{
+ public AsyncReactiveCommand HeavyCommand { get; }
+
+ public ReactiveProperty Message { get; } = new ReactiveProperty();
+
+ public ViewModel()
+ {
+ HeavyCommand = new AsyncReactiveCommand()
+ .WithSubscribe(async () =>
+ {
+ Message.Value = "Heavy command started.";
+ await Task.Delay(TimeSpan.FromSeconds(5));
+ Message.Value = "Heavy command finished.";
+ });
+ }
+}
+```
+
+```xml
+
+
+
+
+
+
+```
+
+
+
+もちろん、`AsyncReactiveCommand` は `IObservable` からも作成できます。
+
+```csharp
+public class ViewModel
+{
+ public AsyncReactiveCommand HeavyCommand { get; }
+
+ public ReactiveProperty Message { get; } = new ReactiveProperty();
+
+ public ViewModel()
+ {
+ HeavyCommand = Observable.Interval(TimeSpan.FromSeconds(1))
+ .Select(x => x % 2 == 0)
+ .ToAsyncReactiveCommand()
+ .WithSubscribe(async () =>
+ {
+ Message.Value = "Heavy command started.";
+ await Task.Delay(TimeSpan.FromSeconds(5));
+ Message.Value = "Heavy command finished.";
+ });
+ }
+}
+```
+
+
+
+`AsyncReactiveCommand` クラスも `IDisposable` インターフェイスを実装しています。
+別のインスタンスのイベントを購読する場合は、`Dispose` メソッドを呼び出してください。
+
+### `CanExecute` 状態を共有する
+
+ページ上で一度に 1 つの async メソッドだけを実行したい場合があります。
+この場合、`AsyncReactiveCommand` インスタンス間で `CanExecute` 状態を共有できます。
+同じ `IReactiveProperty` インスタンスから作成すると、`CanExecute` 状態を同期できます。
+
+```csharp
+public class ViewModel
+{
+ private ReactiveProperty HeavyCommandCanExecuteState { get; } = new ReactiveProperty(true);
+ public AsyncReactiveCommand HeavyCommand1 { get; }
+ public AsyncReactiveCommand HeavyCommand2 { get; }
+
+ public ReactiveProperty Message { get; } = new ReactiveProperty();
+
+ public ViewModel()
+ {
+ HeavyCommand1 = HeavyCommandCanExecuteState
+ .ToAsyncReactiveCommand()
+ .WithSubscribe(async () =>
+ {
+ Message.Value = "Heavy command 1 started.";
+ await Task.Delay(TimeSpan.FromSeconds(5));
+ Message.Value = "Heavy command 1 finished.";
+ });
+ HeavyCommand2 = HeavyCommandCanExecuteState
+ .ToAsyncReactiveCommand()
+ .WithSubscribe(async () =>
+ {
+ Message.Value = "Heavy command 2 started.";
+ await Task.Delay(TimeSpan.FromSeconds(5));
+ Message.Value = "Heavy command 2 finished.";
+ });
+ }
+}
+```
+
+```xml
+
+
+
+
+
+
+
+```
+
+
+
+もちろん、`IObservable` と `IReactiveProperty` を組み合わせることもできます。`AsyncReactiveCommand` のソースとして `IObservable` を使い、複数の `AsyncReactiveCommand` で状態を共有するために `IReactiveProperty` を使います。
+次のように、`ToAsyncReactiveCommand(this IObservable source, IReactiveProperty sharedCanExecute = null)` メソッドを使えます。
+
+```csharp
+using Reactive.Bindings;
+using Reactive.Bindings.Extensions;
+using System.ComponentModel.DataAnnotations;
+using System.Threading.Tasks;
+
+namespace RPSample
+{
+ public class MainPageViewModel
+ {
+ // 共有状態用
+ private ReactivePropertySlim SharedCanExecute { get; }
+ // コマンド ソース用
+ [Required]
+ public ReactiveProperty Input { get; }
+
+ // コマンド
+ public AsyncReactiveCommand CommandA { get; }
+ public AsyncReactiveCommand CommandB { get; }
+
+ public MainPageViewModel()
+ {
+ Input = new ReactiveProperty().SetValidateAttribute(() => Input);
+
+ // CanExecute 状態を共有するため、同じソースと同じ IReactiveProperty から AsyncReactiveCommand を作成します。
+ SharedCanExecute = new ReactivePropertySlim(true);
+ CommandA = Input.ObserveHasErrors
+ .Inverse()
+ .ToAsyncReactiveCommand(SharedCanExecute)
+ .WithSubscribe(() => Task.Delay(3000));
+ CommandB = Input.ObserveHasErrors
+ .Inverse()
+ .ToAsyncReactiveCommand(SharedCanExecute)
+ .WithSubscribe(() => Task.Delay(3000));
+ }
+ }
+}
+```
+
+ViewModel クラスを View にバインディングした後は次のようになります。
+
+```csharp
+// コード ビハインド
+using Windows.UI.Xaml.Controls;
+
+namespace RPSample
+{
+ public sealed partial class MainPage : Page
+ {
+ private MainPageViewModel ViewModel { get; } = new MainPageViewModel();
+ public MainPage()
+ {
+ InitializeComponent();
+ }
+ }
+}
+```
+
+```xml
+
+
+
+
+
+
+
+
+```
+
+動作は次のようになります。
+
+
+
+
+## スレッド処理
+
+### `ReactiveCommand` クラス
+
+`ReactiveCommand` クラスを使うと、このクラスはスケジューラー上で `CanExecute` イベントを発生させます(既定は UI スレッド スケジューラーです)。この動作を変更したい場合は、`IScheduler` 引数を持つ `ToReactiveCommand` のオーバーロードを使います。
+
+次の例を参照してください。
+
+```csharp
+canExecuteSource.ToReactiveCommand(theSchedulerInstanceYouWant);
+```
+
+### `AsyncReactiveCommand` クラス
+
+`AsyncReactiveCommand` クラスはスレッドを自動的に変更しません。スレッドを変更したい場合は、`ObserveOn` メソッドを使います。
+
+次の例を参照してください。
+
+```csharp
+canExecuteSource.ObserveOn(theSchedulerInstanceYouWant).ToAsyncReactiveCommand();
+```
+
+### `ReactiveCommandSlim`
+
+これは `ReactiveCommand` の軽量版です。従来の `ReactiveCommand` との主な違いは、`CanExecuteChanged` イベントが UI スレッドへディスパッチされなくなったことです。常に UI スレッドでイベントを発生させる必要がある場合は、`ReactiveCommandSlim` のソースである `IObservable` に対して `ObserveOn` メソッドを使い、明示的に設定してください。
+
+さらに、`ReactivePropertySlim` と同じ方法で実装することで、さまざまな性能改善が行われています。ベンチマークは次のとおりです。
+
+| メソッド | 平均 | エラー | 標準偏差 | 中央値 |
+|---------------------------------------------- |-------------:|------------:|------------:|-------------:|
+| CreateReactiveCommand | 291.931 ns | 5.6965 ns | 10.5589 ns | 291.178 ns |
+| CreateReactiveCommandSlim | 4.313 ns | 0.1293 ns | 0.1080 ns | 4.269 ns |
+| BasicUsecaseForReactiveCommand | 1,187.294 ns | 22.8930 ns | 21.4141 ns | 1,179.896 ns |
+| BasicUsecaseForReactiveCommandSlim | 91.861 ns | 1.8934 ns | 3.5096 ns | 91.750 ns |
+
+上から順に、`ReactiveCommand` の作成、`ReactiveCommandSlim` の作成、`ReactiveCommand` の基本的なユースケース、`ReactiveCommandSlim` の基本的なユースケースを表しています。インスタンス化では 70 倍以上、基本機能の利用では 13 倍の性能差があります。
+
+さらに、`AsyncReactiveCommand` と同様に、`IReactiveProperty` を共有することで複数のコマンド間で実行状態を簡単に共有できます。
diff --git a/docs/docs-ja/features/Event-transfer-to-ViewModel-from-View.md b/docs/docs-ja/features/Event-transfer-to-ViewModel-from-View.md
new file mode 100644
index 00000000..3423a11b
--- /dev/null
+++ b/docs/docs-ja/features/Event-transfer-to-ViewModel-from-View.md
@@ -0,0 +1,169 @@
+# View から ViewModel へイベントを転送する
+
+`EventToReactiveProperty` クラスと `EventToReactiveCommand` クラスは、View レイヤーからのイベントを `ReactiveProperty` または `ReactiveCommand` に転送します。
+これらのクラスは `TriggerAction` を拡張しており、`EventTrigger` と一緒に使うように設計されています。
+
+メモ:
+> この機能は WPF と UWP でのみ利用できます。Xamarin.Forms では使えません。使いたい場合は、WPF では `ReactiveProperty.WPF` パッケージを、UWP では `ReactiveProperty.UWP` パッケージをプロジェクトに追加してください。
+
+これらのクラスは、`ReactiveConverter` を使って `EventArgs` を任意のオブジェクト型に変換できます。
+
+`ReactiveConverter` クラスでは Rx のメソッド チェーンを使用できます。非常に強力です。
+
+
+UWP のサンプル:
+
+```csharp
+using Reactive.Bindings.Interactivity;
+using System;
+using System.Linq;
+using System.Reactive.Linq;
+using Windows.Storage.Pickers;
+using Windows.UI.Xaml;
+
+namespace App1
+{
+ public class FileOpenReactiveConverter : ReactiveConverter
+ {
+ protected override IObservable OnConvert(IObservable source)
+ {
+ return source.SelectMany(async _ =>
+ {
+ var picker = new FileOpenPicker();
+ picker.FileTypeFilter.Add(".snippet");
+ var f = await picker.PickSingleFileAsync();
+ return f?.Path;
+ })
+ .Where(x => x != null);
+
+ }
+ }
+}
+```
+
+これは `RoutedEventArgs` をファイル パスに変換します。
+
+XAML とコード ビハインドは次のとおりです。
+
+```xml
+
+
+
+
+
+
+```
+
+```csharp
+using Reactive.Bindings;
+using Windows.UI.Xaml.Controls;
+
+namespace App1
+{
+ public sealed partial class MainPage : Page
+ {
+ public MainPageViewModel ViewModel { get; } = new MainPageViewModel();
+
+ public MainPage()
+ {
+ this.InitializeComponent();
+ }
+ }
+
+ public class MainPageViewModel
+ {
+ public ReactiveCommand SelectFileCommand { get; }
+ public ReadOnlyReactiveProperty FileName { get; }
+
+ public MainPageViewModel()
+ {
+ this.SelectFileCommand = new ReactiveCommand();
+ this.FileName = this.SelectFileCommand.ToReadOnlyReactiveProperty();
+ }
+ }
+
+}
+```
+
+
+
+
+`EventToReactiveProperty` は、`ReactiveConverter` で変換された値を `ReactiveProperty` に設定します。
+
+```xml
+
+
+
+
+
+
+```
+
+```csharp
+using Reactive.Bindings;
+using Windows.UI.Xaml.Controls;
+
+namespace App1
+{
+ public sealed partial class MainPage : Page
+ {
+ public MainPageViewModel ViewModel { get; } = new MainPageViewModel();
+
+ public MainPage()
+ {
+ this.InitializeComponent();
+ }
+ }
+
+ public class MainPageViewModel
+ {
+ public ReactiveProperty FileName { get; } = new ReactiveProperty();
+ }
+
+}
+```
+
+## EventToReactiveCommand のカスタマイズ
+
+### CallExecuteOnScheduler プロパティ
+
+既定の動作では、`ReactivePropertyScheduler.Default` に設定された `IScheduler` 上でコマンドの Execute メソッドを呼び出します。この動作を無効にするには、このプロパティを false に設定します。
+
+### AutoEnable プロパティ
+
+既定の動作では、AssociatedObject.IsEnabled とコマンドの CanExecute が自動的に同期されます。
+この動作を無効にするには、このプロパティを false に設定します。
diff --git a/docs/docs-ja/features/Extension-methods.md b/docs/docs-ja/features/Extension-methods.md
new file mode 100644
index 00000000..3b15224a
--- /dev/null
+++ b/docs/docs-ja/features/Extension-methods.md
@@ -0,0 +1,364 @@
+# 拡張メソッド
+
+`Reactive.Bindings.Extensions` 名前空間は便利な拡張メソッドを提供します。
+
+## `AddTo`
+
+この名前空間の中でも、とても便利な拡張メソッドです。
+メソッド チェーンの中で `IDisposable` インスタンスを集約できます。
+
+このメソッドがない場合、インスタンス作成用と `IDisposable` インスタンス追加用の 2 つの文が必要です。
+
+```csharp
+// 初期化
+var d = new CompositeDisposable();
+
+Name = model.ObserveProperty(x => x.Name)
+ .ToReadOnlyReactiveProperty();
+d.Add(Name);
+
+Age = model.ObserveProperty(x => x.Age)
+ .ToReadOnlyReactiveProperty();
+d.Add(Age);
+
+// すべて破棄
+d.Dispose();
+```
+
+`AddTo` 拡張メソッドのサンプル コードです。
+
+```csharp
+// 初期化
+var d = new CompositeDisposable();
+
+Name = model.ObserveProperty(x => x.Name)
+ .ToReadOnlyReactiveProperty()
+ .AddTo(d);
+
+Age = model.ObserveProperty(x => x.Age)
+ .ToReadOnlyReactiveProperty()
+ .AddTo(d);
+
+// すべて破棄
+d.Dispose();
+```
+
+とても便利です。
+
+## `CatchIgnore`
+
+この拡張メソッドは例外を捕捉し、`Observable.Empty` を返します。
+
+```csharp
+source.CatchIgnore((Exception ex) => { ... error action ... })
+ .Subscribe();
+```
+
+## `CombineLatestValuesAreAllXXXX`
+
+2 つのメソッドを提供します。
+
+- `CombineLatestValuesAreAllTrue`
+- `CombineLatestValuesAreAllFalse`
+
+これらは単なるショートカットです。
+
+```csharp
+///
+/// 各シーケンスの最新値がすべて true です。
+///
+public static IObservable CombineLatestValuesAreAllTrue(
+ this IEnumerable> sources) =>
+ sources.CombineLatest(xs => xs.All(x => x));
+
+
+///
+/// 各シーケンスの最新値がすべて false です。
+///
+public static IObservable CombineLatestValuesAreAllFalse(
+ this IEnumerable> sources) =>
+ sources.CombineLatest(xs => xs.All(x => !x));
+```
+
+## DisposePreviousValue
+
+この拡張メソッドは、`IObservable` シーケンスの前の値に対して `Dispose` メソッドを呼び出します。
+
+```csharp
+var source = new Subject();
+var rrp = source.Select(x => new SomeDisposableClass(x))
+ .DisposePreviousValue()
+ .ToReadOnlyReactivePropertySlim();
+
+source.OnNext("first"); // first の SomeDisposableClass が作成されます。
+source.OnNext("second"); // second の SomeDisposableClass が作成され、first は破棄されます。
+source.OnCompleted(); // second も破棄されます。
+```
+
+## `CanExecuteChangedAsObservable`
+
+これは `ICommand` インターフェイスの拡張メソッドです。
+`Observable.FromEvent` のショートカットです。
+
+```csharp
+/// CanExecuteChanged を Observable シーケンスに変換します。
+public static IObservable CanExecuteChangedAsObservable(this T source)
+ where T : ICommand =>
+ Observable.FromEvent(
+ h => (sender, e) => h(e),
+ h => source.CanExecuteChanged += h,
+ h => source.CanExecuteChanged -= h);
+```
+
+## `INotifyCollectionChanged` 拡張メソッド
+
+`CollectionChanged` イベントを `IObservable` に変換します。
+
+```csharp
+/// CollectionChanged:Remove を監視し、単一の項目を取り出します。
+public static IObservable ObserveRemoveChanged(this INotifyCollectionChanged source) =>
+ source.CollectionChangedAsObservable()
+ .Where(e => e.Action == NotifyCollectionChangedAction.Remove)
+ .Select(e => (T)e.OldItems[0]);
+
+/// CollectionChanged:Remove を監視します。
+public static IObservable ObserveRemoveChangedItems(this INotifyCollectionChanged source) =>
+ source.CollectionChangedAsObservable()
+ .Where(e => e.Action == NotifyCollectionChangedAction.Remove)
+ .Select(e => e.OldItems.Cast().ToArray());
+
+/// CollectionChanged:Move を監視し、単一の項目を取り出します。
+public static IObservable> ObserveMoveChanged(this INotifyCollectionChanged source) =>
+ source.CollectionChangedAsObservable()
+ .Where(e => e.Action == NotifyCollectionChangedAction.Move)
+ .Select(e => new OldNewPair((T)e.OldItems[0], (T)e.NewItems[0]));
+
+/// CollectionChanged:Move を監視します。
+public static IObservable> ObserveMoveChangedItems(this INotifyCollectionChanged source) =>
+ source.CollectionChangedAsObservable()
+ .Where(e => e.Action == NotifyCollectionChangedAction.Move)
+ .Select(e => new OldNewPair(e.OldItems.Cast().ToArray(), e.NewItems.Cast().ToArray()));
+
+/// CollectionChanged:Replace を監視し、単一の項目を取り出します。
+public static IObservable> ObserveReplaceChanged(this INotifyCollectionChanged source) =>
+ source.CollectionChangedAsObservable()
+ .Where(e => e.Action == NotifyCollectionChangedAction.Replace)
+ .Select(e => new OldNewPair((T)e.OldItems[0], (T)e.NewItems[0]));
+
+/// CollectionChanged:Replace を監視します。
+public static IObservable> ObserveReplaceChangedItems(this INotifyCollectionChanged source) =>
+ source.CollectionChangedAsObservable()
+ .Where(e => e.Action == NotifyCollectionChangedAction.Replace)
+ .Select(e => new OldNewPair(e.OldItems.Cast().ToArray(), e.NewItems.Cast().ToArray()));
+
+/// CollectionChanged:Reset を監視します。
+public static IObservable ObserveResetChanged(this INotifyCollectionChanged source) =>
+ source.CollectionChangedAsObservable()
+ .Where(e => e.Action == NotifyCollectionChangedAction.Reset)
+ .Select(_ => new Unit());
+```
+
+## `ObservableCollection` 拡張メソッド
+
+これは `INotifyPropertyChanged` 拡張メソッドの型安全なバージョンです。
+
+```csharp
+/// CollectionChanged:Add を監視し、単一の項目を取り出します。
+public static IObservable ObserveAddChanged(this ObservableCollection source) =>
+ ((INotifyCollectionChanged)source).ObserveAddChanged();
+
+/// CollectionChanged:Add を監視します。
+public static IObservable ObserveAddChangedItems(this ObservableCollection source) =>
+ ((INotifyCollectionChanged)source).ObserveAddChangedItems();
+
+/// CollectionChanged:Remove を監視し、単一の項目を取り出します。
+public static IObservable ObserveRemoveChanged(this ObservableCollection source) =>
+ ((INotifyCollectionChanged)source).ObserveRemoveChanged();
+
+/// CollectionChanged:Remove を監視します。
+public static IObservable ObserveRemoveChangedItems(this ObservableCollection source) =>
+ ((INotifyCollectionChanged)source).ObserveRemoveChangedItems();
+
+/// CollectionChanged:Move を監視し、単一の項目を取り出します。
+public static IObservable> ObserveMoveChanged(this ObservableCollection source) =>
+ ((INotifyCollectionChanged)source).ObserveMoveChanged();
+
+/// CollectionChanged:Move を監視します。
+public static IObservable> ObserveMoveChangedItems(this ObservableCollection source) =>
+ ((INotifyCollectionChanged)source).ObserveMoveChangedItems();
+
+/// CollectionChanged:Replace を監視し、単一の項目を取り出します。
+public static IObservable> ObserveReplaceChanged(this ObservableCollection source) =>
+ ((INotifyCollectionChanged)source).ObserveReplaceChanged();
+
+/// CollectionChanged:Replace を監視します。
+public static IObservable> ObserveReplaceChangedItems(this ObservableCollection source) =>
+ ((INotifyCollectionChanged)source).ObserveReplaceChangedItems();
+
+/// CollectionChanged:Reset を監視します。
+public static IObservable ObserveResetChanged(this ObservableCollection source) =>
+ ((INotifyCollectionChanged)source).ObserveResetChanged();
+```
+
+## `ObservableCollection` と `IFilteredReadOnlyObservableCollection` の要素の `PropertyChanged` イベントを監視する
+
+`ObservableCollection` と `IFilteredReadOnlyObservableCollection` 内の要素の `PropertyChanged` イベントを監視します。
+`ObserveElementProperty` 拡張メソッドでは、特定のプロパティの `PropertyChanged` イベントを監視できます。
+
+```csharp
+using Reactive.Bindings.Extensions;
+using System;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+
+namespace ReactivePropertyEduApp
+{
+ public class Person : INotifyPropertyChanged
+ {
+ public event PropertyChangedEventHandler PropertyChanged;
+ private string _name;
+ public string Name
+ {
+ get => _name;
+ set
+ {
+ _name = value;
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
+ }
+ }
+ }
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ var c = new ObservableCollection();
+ c.ObserveElementProperty(x => x.Name)
+ .Subscribe(x => Console.WriteLine($"Subscribe: {x.Instance}, {x.Property.Name}, {x.Value}"));
+
+ var neuecc = new Person { Name = "neuecc" };
+ var xin9le = new Person { Name = "xin9le" };
+ var okazuki = new Person { Name = "okazuki" };
+
+ Console.WriteLine("Add items");
+ c.Add(neuecc);
+ c.Add(xin9le);
+ c.Add(okazuki);
+
+ Console.WriteLine("Change okazuki name to Kazuki Ota");
+ okazuki.Name = "Kazuki Ota";
+
+ Console.WriteLine("Remove okazuki from collection");
+ c.Remove(okazuki);
+
+ Console.WriteLine("Change okazuki name to okazuki");
+ okazuki.Name = "okazuki";
+ }
+ }
+}
+```
+
+```
+Add items
+Subscribe: ReactivePropertyEduApp.Person, Name, neuecc
+Subscribe: ReactivePropertyEduApp.Person, Name, xin9le
+Subscribe: ReactivePropertyEduApp.Person, Name, okazuki
+Change okazuki name to Kazuki Ota
+Subscribe: ReactivePropertyEduApp.Person, Name, Kazuki Ota
+Remove okazuki from collection
+Change okazuki name to okazuki
+```
+
+対象オブジェクトのプロパティ型が `ReactiveProperty` の場合は、`ObserveElementObservableProperty` 拡張メソッドを使います。
+
+```csharp
+using Reactive.Bindings;
+using Reactive.Bindings.Extensions;
+using System;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+
+namespace ReactivePropertyEduApp
+{
+ public class Person
+ {
+ public ReactiveProperty Name { get; }
+
+ public Person(string name)
+ {
+ Name = new ReactiveProperty(name);
+ }
+ }
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ var c = new ObservableCollection();
+ c.ObserveElementObservableProperty(x => x.Name)
+ .Subscribe(x => Console.WriteLine($"Subscribe: {x.Instance}, {x.Property.Name}, {x.Value}"));
+
+ var neuecc = new Person("neuecc");
+ var xin9le = new Person("xin9le");
+ var okazuki = new Person("okazuki");
+
+ Console.WriteLine("Add items");
+ c.Add(neuecc);
+ c.Add(xin9le);
+ c.Add(okazuki);
+
+ Console.WriteLine("Change okazuki name to Kazuki Ota");
+ okazuki.Name.Value = "Kazuki Ota";
+
+ Console.WriteLine("Remove okazuki from collection");
+ c.Remove(okazuki);
+
+ Console.WriteLine("Change okazuki name to okazuki");
+ okazuki.Name.Value = "okazuki";
+ }
+ }
+}
+```
+
+```
+Add items
+Subscribe: ReactivePropertyEduApp.Person, Name, neuecc
+Subscribe: ReactivePropertyEduApp.Person, Name, xin9le
+Subscribe: ReactivePropertyEduApp.Person, Name, okazuki
+Change okazuki name to Kazuki Ota
+Subscribe: ReactivePropertyEduApp.Person, Name, Kazuki Ota
+Remove okazuki from collection
+Change okazuki name to okazuki
+```
+
+## `INotifyDataErrorInfo` 拡張メソッド
+
+`ErrorsChanged` イベントを `IObservable` に変換します。
+`FromEvent` メソッドのショートカットです。
+
+```csharp
+/// ErrorsChanged を Observable シーケンスに変換します。
+public static IObservable ErrorsChangedAsObservable(this T subject)
+ where T : INotifyDataErrorInfo =>
+ Observable.FromEvent, DataErrorsChangedEventArgs>(
+ h => (sender, e) => h(e),
+ h => subject.ErrorsChanged += h,
+ h => subject.ErrorsChanged -= h);
+```
+
+`ObserveErrorInfo` 拡張メソッドは、`ErrorsChanged` イベントが発生したときにプロパティ値を発行します。
+
+## `Inverse`
+
+`IObservable` シーケンスの bool 値を反転します。
+
+```csharp
+IObservable boolSequence = ...;
+IObservable inversedBoolSequence = boolSequence.Inverse();
+```
+
+これは次のコードと同じです。
+
+```csharp
+IObservable boolSequence = ...;
+IObservable inversedBoolSequence = boolSequence.Select(x => !x);
+```
+
diff --git a/docs/docs-ja/features/Notifiers.md b/docs/docs-ja/features/Notifiers.md
new file mode 100644
index 00000000..7b06f6a6
--- /dev/null
+++ b/docs/docs-ja/features/Notifiers.md
@@ -0,0 +1,272 @@
+# 通知クラス
+
+`Reactive.Bindings.Notifiers` 名前空間は、`IObservable` インターフェイスを実装する多くの便利なクラスを提供します。
+
+## `BooleanNotifier`
+
+`BooleanNotifier` クラスは `IObservable` インターフェイスを実装しています。
+いくつかのメソッドとプロパティを持っています。
+
+- `TurnOn` メソッド
+ - 状態を true に変更します。
+- `TurnOff` メソッド
+ - 状態を false に変更します。
+- `SwitchValue` メソッド
+ - 状態を切り替えます。
+- `Value` プロパティ
+ - 状態を設定します。
+
+初期状態はコンストラクターで設定できます。既定値は false です。
+
+
+```csharp
+var n = new BooleanNotifier();
+n.Subscribe(x => Debug.WriteLine(x));
+
+n.TurnOn(); // true
+n.TurnOff(); // false
+n.Value = true; // true
+n.Value = false; // false
+```
+
+次のように `ReactiveCommand` のソースとして使えます。
+
+```csharp
+var n = new BooleanNotifier(); // 既定値は false です。
+
+// ReactiveCommand の CanExecute メソッドは既定で true を返すため、initialValue に `n.Value` を明示的に設定します。
+var command = n.ToReactiveCommand(initialValue: n.Value);
+
+// または、ToReactiveCommand を呼び出す前に Select などの演算子で何かに変換したい場合は、StartWith を使えます。
+var command2 = n.StartWith(n.Value).Select(x => Something(x)).ToReactiveCommand();
+```
+
+## `CountNotifier`
+
+`CountNotifier` クラスは `IObservable` インターフェイスを実装しています。インクリメントとデクリメント機能を提供し、状態が変わると `CountChangedStatus` 値を発行します。
+
+CountChangedStatus enum は次のように定義されています。
+
+```csharp
+/// CountNotifier のイベント種別です。
+public enum CountChangedStatus
+{
+ /// カウントがインクリメントされました。
+ Increment,
+ /// カウントがデクリメントされました。
+ Decrement,
+ /// カウントは 0 です。
+ Empty,
+ /// カウントが最大値に達しました。
+ Max
+}
+```
+
+`CountNotifier` の最大値はコンストラクター引数から設定できます。
+
+```csharp
+var c = new CountNotifier(); // 既定の最大値は int.MaxValue です
+// 状態を出力します。
+c.Subscribe(x => Debug.WriteLine(x));
+// 現在の値を出力します。
+c.Select(_ => c.Count).Subscribe(x => Debug.WriteLine(x));
+// インクリメント
+var d = c.Increment(10);
+// インクリメントを元に戻します
+d.Dispose();
+// インクリメントとデクリメント
+c.Increment(10);
+c.Decrement(5);
+// 現在の値を出力します。
+Debug.WriteLine(c.Count);
+```
+
+出力は次のとおりです。
+
+```
+Increment
+10
+Decrement
+0
+Empty
+0
+Increment
+10
+Decrement
+5
+5
+```
+
+## `ScheduledNotifier`
+
+このクラスはスケジューラー上で値を発行します。既定のスケジューラーは `Scheduler.Immediate` です。コンストラクター引数を使ってスケジューラーを設定します。
+
+```csharp
+var n = new ScheduledNotifier();
+n.Subscribe(x => Debug.WriteLine(x));
+// 値をすぐに出力します
+n.Report("Hello world");
+// 2 秒後に値を出力します。
+n.Report("After 2 seconds.", TimeSpan.FromSeconds(2));
+```
+
+## `BusyNotifier`
+
+このクラスは `IObservable` インターフェイスを実装しています。
+処理の実行中は `true` を発行し、すべての処理が終了すると `false` を発行します。
+
+`ProcessStart` メソッドは `IDisposable` インスタンスを返します。処理が終了したら、Dispose メソッドを呼び出します。
+
+
+```csharp
+using Reactive.Bindings.Notifiers;
+using System;
+using System.Threading.Tasks;
+
+namespace ReactivePropertyEduApp
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ MainAsync(args).Wait();
+ }
+
+ static async Task MainAsync(string[] args)
+ {
+ var b = new BusyNotifier();
+ b.Subscribe(x => Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss")}: OnNext: {x}"));
+
+ await Task.WhenAll(
+ Task.Run(async () =>
+ {
+ using (b.ProcessStart())
+ {
+ Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss")}: Process1 started.");
+ await Task.Delay(TimeSpan.FromSeconds(1));
+ Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss")}: Process1 finished.");
+ }
+ }),
+ Task.Run(async () =>
+ {
+ using (b.ProcessStart())
+ {
+ Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss")}: Process2 started.");
+ await Task.Delay(TimeSpan.FromSeconds(2));
+ Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss")}: Process2 finished.");
+ }
+ }));
+ }
+ }
+}
+```
+
+出力は次のとおりです。
+
+```
+15:07:45: OnNext: False
+15:07:45: OnNext: True
+15:07:45: Process1 started.
+15:07:45: Process2 started.
+15:07:46: Process1 finished.
+15:07:47: Process2 finished.
+15:07:47: OnNext: False
+```
+
+
+## `MessageBroker`
+
+`MessageBroker` はインメモリの pub-sub notifier です。`EventAggregator` や `MessageBus` に似ており、Rx と async に適しています。messenger パターンに利用できます。
+
+```csharp
+using Reactive.Bindings.Notifiers;
+using System;
+using System.Reactive.Linq;
+using System.Threading.Tasks;
+
+public class MyClass
+{
+ public int MyProperty { get; set; }
+
+ public override string ToString()
+ {
+ return "MP:" + MyProperty;
+ }
+}
+class Program
+{
+ static void RunMessageBroker()
+ {
+ // グローバル スコープの pub-sub メッセージング
+ MessageBroker.Default.Subscribe(x =>
+ {
+ Console.WriteLine("A:" + x);
+ });
+
+ var d = MessageBroker.Default.Subscribe(x =>
+ {
+ Console.WriteLine("B:" + x);
+ });
+
+ // IObservable への変換をサポート
+ MessageBroker.Default.ToObservable().Subscribe(x =>
+ {
+ Console.WriteLine("C:" + x);
+ });
+
+ MessageBroker.Default.Publish(new MyClass { MyProperty = 100 });
+ MessageBroker.Default.Publish(new MyClass { MyProperty = 200 });
+ MessageBroker.Default.Publish(new MyClass { MyProperty = 300 });
+
+ d.Dispose(); // 購読解除
+ MessageBroker.Default.Publish(new MyClass { MyProperty = 400 });
+ }
+
+ static async Task RunAsyncMessageBroker()
+ {
+ // 非同期の message pub-sub
+ AsyncMessageBroker.Default.Subscribe(async x =>
+ {
+ Console.WriteLine("A:" + x);
+ await Task.Delay(TimeSpan.FromSeconds(1));
+ });
+
+ var d = AsyncMessageBroker.Default.Subscribe(async x =>
+ {
+ Console.WriteLine("B:" + x);
+ await Task.Delay(TimeSpan.FromSeconds(2));
+ });
+
+ // すべての subscriber の完了を待ちます
+ await AsyncMessageBroker.Default.PublishAsync(new MyClass { MyProperty = 100 });
+ await AsyncMessageBroker.Default.PublishAsync(new MyClass { MyProperty = 200 });
+ await AsyncMessageBroker.Default.PublishAsync(new MyClass { MyProperty = 300 });
+
+ d.Dispose(); // 購読解除
+ await AsyncMessageBroker.Default.PublishAsync(new MyClass { MyProperty = 400 });
+ }
+
+ static void Main(string[] args)
+ {
+ Console.WriteLine("MessageBroker");
+ RunMessageBroker();
+
+ Console.WriteLine("AsyncMessageBroker");
+ RunAsyncMessageBroker().Wait();
+ }
+}
+```
+
+messenger パターンのマルチスレッド ディスパッチは、Rx で簡単に扱えます。
+
+```csharp
+MessageBroker.Default.ToObservable()
+ .ObserveOn(Dispatcher) // Rx の魔法!
+ .Subscribe(x =>
+ {
+ Console.WriteLine(x);
+ });
+```
+
+
+
diff --git a/docs/docs-ja/features/ReactiveProperty.md b/docs/docs-ja/features/ReactiveProperty.md
new file mode 100644
index 00000000..caf70b0f
--- /dev/null
+++ b/docs/docs-ja/features/ReactiveProperty.md
@@ -0,0 +1,614 @@
+# ReactiveProperty
+
+`ReactiveProperty` はこのライブラリの中核となるクラスです。
+次の機能を備えています。
+
+- `INotifyPropertyChanged` インターフェイスを実装しています。
+ - Value プロパティは `PropertyChanged` イベントを発生させます。
+- `IObservable` インターフェイスを実装しています。
+
+はい、Value プロパティは XAML コントロールのプロパティへバインディングできます。
+また、このクラスは値が設定されたときに `IObserver` の `OnNext` メソッドも呼び出します。
+
+サンプル コードを次に示します。
+
+```csharp
+using Reactive.Bindings;
+using System;
+
+namespace ReactivePropertyEduApp
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ // 既定のコンストラクターから作成します(既定値は null)。
+ var name = new ReactiveProperty();
+ // イベント ハンドラーと OnNext コールバックを設定します。
+ name.PropertyChanged += (_, e) => Console.WriteLine($"PropertyChanged: {e.PropertyName}");
+ name.Subscribe(x => Console.WriteLine($"OnNext: {x}"));
+
+ // Value プロパティを更新します。
+ name.Value = "neuecc";
+ name.Value = "xin9le";
+ name.Value = "okazuki";
+ }
+ }
+}
+```
+
+このプログラムの出力は次のとおりです。
+
+```
+OnNext:
+OnNext: neuecc
+PropertyChanged: Value
+OnNext: xin9le
+PropertyChanged: Value
+OnNext: okazuki
+PropertyChanged: Value
+```
+
+`PropertyChanged` コールバックと `OnNext` コールバックの違いは何でしょうか。
+`OnNext` コールバックは購読時に呼び出されます。`PropertyChanged` はイベント ハンドラーが追加されても呼び出されません。また、`OnNext` コールバックの引数はプロパティ値ですが、`PropertyChanged` の引数にはプロパティ値がありません。
+
+`PropertyChanged` イベントはデータ バインディングのために提供されています。通常は Reactive Extensions のメソッドを使うべきです。
+
+## XAML プラットフォームで使う
+
+`ReactiveProperty` クラスは、WPF、UWP、Xamarin.Forms などの XAML プラットフォーム向けに設計されています。
+このクラスは ViewModel レイヤーで使用できます。
+
+`ReactiveProperty` を使わない場合、ViewModel クラスは次のようになります。
+
+```csharp
+public class MainPageViewModel : INotifyPropertyChanged
+{
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ private string _name;
+ public string Name
+ {
+ get => _name;
+ set
+ {
+ _name = value;
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
+ }
+ }
+
+ // 他のプロパティも同様のコードで定義します。
+}
+```
+
+これらのプロパティは XAML コードでバインディングします。
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+```
+
+`ReactiveProperty` を使うと、ViewModel のコードはとてもシンプルになります。
+
+```csharp
+// WPF で使用する場合は、INotifyPropertyChanged インターフェイスを実装する必要があります。
+// そうしないとメモリ リークが発生する可能性があります。
+public class MainPageViewModel
+{
+ public ReactiveProperty Name { get; } = new ReactiveProperty();
+
+ // 他のプロパティも同様のコードで定義します。
+}
+```
+
+XAML コードでバインディングするときは、バインディング パスに `.Value` を追加する必要があります。
+これがこのライブラリの唯一の制限です。
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+```
+
+> `.Value` を忘れてしまうことがあります。ReSharper ライセンスをお持ちの場合は、このプラグインを利用できます。
+> [ReactiveProperty XAML Binding Corrector](https://resharper-plugins.jetbrains.com/packages/ReSharper.RpCorrector/)
+> XAML で ReactiveProperty の ".Value" バインディングが不足している箇所を強調表示します。
+
+## `ReactiveProperty` インスタンスの作成方法
+
+`ReactiveProperty` クラスはさまざまな方法で作成できます。
+
+### コンストラクターから作成する
+
+最も簡単な方法は、コンストラクターを使うことです。
+
+```csharp
+// 既定値で作成します。
+var name = new ReactiveProperty();
+Console.WriteLine(name.Value); // -> 空の出力
+
+// 初期値を指定して作成します。
+var name = new ReactiveProperty("okazuki");
+Console.WriteLine(name.Value); // -> okazuki
+```
+
+### `IObservable` から作成する
+
+`IObservable` から作成できます。
+`ToReactiveProperty` メソッドを呼び出すだけです。
+
+```csharp
+IObservable observableInstance = Observable.Interval(TimeSpan.FromSeconds(1));
+
+// IObservable から ReactiveProperty に変換します。
+ReactiveProperty counter = observableInstance.ToReactiveProperty();
+```
+
+#### `ReactiveProperty` から作成する
+
+`ReactiveProperty` は `IObservable` インターフェイスを実装しています。
+つまり、`ReactiveProperty` から `ReactiveProperty` を作成できます。
+
+```csharp
+var name = new ReactiveProperty("");
+
+var formalName = name.Select(x => $"Dear {x}")
+ .ToReactiveProperty();
+```
+
+すべての `IObservable` インスタンスは `ReactiveProperty` になれます。
+
+## 検証
+
+`ReactiveProperty` クラスは `INotifyDataErrorInfo` インターフェイスを実装しています。
+
+### カスタム検証ロジックを設定する
+
+`SetValidateNotifyError` メソッドを使ってカスタム検証ロジックを設定できます。
+
+```csharp
+var name = new ReactiveProperty()
+ .SetValidateNotifyError(x => string.IsNullOrWhiteSpace(x) ? "Error message" : null);
+```
+
+値が正しい場合、検証ロジックは null を返す必要があります。
+値が不正な場合、検証ロジックはエラー メッセージを返す必要があります。
+
+### DataAnnotations と連携する
+
+このクラスは DataAnnotations と連携できます。
+`SetValidateAttribute` メソッドを使って検証属性を設定できます。
+
+```csharp
+class ViewModel
+{
+ // 検証属性を設定します
+ [Required(ErrorMessage = "The name is required.")]
+ [StringLength(100, ErrorMessage = "The name length should be lower than 30.")]
+ public ReactiveProperty Name { get; }
+
+ public ViewModel()
+ {
+ Name = new ReactiveProperty()
+ // 検証属性を ReactiveProperty に設定します。
+ .SetValidateAttribute(() => Name);
+ }
+}
+```
+
+WPF は `INotifyDataErrorInfo` インターフェイスと統合されています。次の例を参照してください。
+
+
+
+### 検証エラーの処理
+
+他のプラットフォームでは、`INotifyDataErrorInfo` インターフェイスからのエラー メッセージを表示できません。
+`ReactiveProperty` クラスには、検証エラーを処理するためのプロパティがいくつかあります。
+
+最初のプロパティは `ObserveErrorChanged` です。
+この型は `IObservable` です。`IEnumerable` をエラー メッセージに変換できます。次の例を参照してください。
+
+```csharp
+class ViewModel
+{
+ // 検証属性を設定します
+ [Required(ErrorMessage = "The name is required.")]
+ [StringLength(100, ErrorMessage = "The name length should be lower than 30.")]
+ public ReactiveProperty Name { get; }
+
+ public ReadOnlyReactiveProperty NameErrorMessage { get; }
+
+ public ViewModel()
+ {
+ Name = new ReactiveProperty()
+ // 検証属性を ReactiveProperty に設定します。
+ .SetValidateAttribute(() => Name);
+
+ // エラー メッセージの処理
+ NameErrorMessage = Name.ObserveErrorChanged
+ .Select(x => x?.OfType()?.FirstOrDefault())
+ .ToReadOnlyReactiveProperty();
+ }
+}
+```
+
+`NameErrorMessage.Value` プロパティをテキスト コントロールにバインディングします。エラー メッセージを表示できます。
+
+UWP の場合は、次の例を参照してください。
+
+```csharp
+public sealed partial class MainPage : Page
+{
+ private ViewModel ViewModel { get; } = new ViewModel();
+ public MainPage()
+ {
+ this.InitializeComponent();
+ }
+}
+```
+
+```xml
+
+
+
+
+
+
+
+```
+
+
+
+ReactiveProperty v7.0.0 以降では、`ObserveErrorChanged.Select(x => x?.OfType()?.FirstOrDefault())` の代わりに `ObserveValidationErrorMessage` 拡張メソッドを使います。上のコードは次のようになります。
+
+```csharp
+class ViewModel
+{
+ // 検証属性を設定します
+ [Required(ErrorMessage = "The name is required.")]
+ [StringLength(100, ErrorMessage = "The name length should be lower than 30.")]
+ public ReactiveProperty Name { get; }
+
+ public ReadOnlyReactiveProperty NameErrorMessage { get; }
+
+ public ViewModel()
+ {
+ Name = new ReactiveProperty()
+ // 検証属性を ReactiveProperty に設定します。
+ .SetValidateAttribute(() => Name);
+
+ // エラー メッセージの処理
+ NameErrorMessage = Name.ObserveValidationErrorMessage()
+ .ToReadOnlyReactiveProperty();
+ }
+}
+```
+
+次のプロパティは `ObserveHasErrors` です。`ObserveHasErrors` プロパティの型は `IObservable` です。
+一般的な入力フォームでは、`ObserveHasErrors` プロパティの値を組み合わせると非常に便利です。
+
+このサンプル プログラムは、2 つの `ReactiveProperty` の `ObserveHasErrors` プロパティを組み合わせて、`ReactiveProperty` 型の `HasErrors` プロパティを作成します。
+
+```csharp
+public class ViewModel
+{
+ // 検証属性を設定します
+ [Required(ErrorMessage = "The name is required.")]
+ [StringLength(100, ErrorMessage = "The name length should be lower than 30.")]
+ public ReactiveProperty Name { get; }
+
+ [Required(ErrorMessage = "The memo is required.")]
+ public ReactiveProperty Memo { get; }
+
+ public ReadOnlyReactiveProperty HasErrors { get; }
+
+ public ViewModel()
+ {
+ Name = new ReactiveProperty()
+ .SetValidateAttribute(() => Name);
+
+ Memo = new ReactiveProperty()
+ .SetValidateAttribute(() => Memo);
+
+ // 複数の ObserveHasErrors 値を組み合わせられます。
+ HasErrors = new[]
+ {
+ Name.ObserveHasErrors,
+ Memo.ObserveHasErrors,
+ }.CombineLatest(x => x.Any(y => y))
+ .ToReadOnlyReactiveProperty();
+ }
+}
+```
+
+```xml
+
+
+
+
+
+
+
+
+
+
+```
+
+
+
+
+
+最後のプロパティは `HasErrors` です。これは単なる `bool` プロパティです。
+
+```csharp
+public class ViewModel
+{
+ // 検証属性を設定します
+ [Required(ErrorMessage = "The name is required.")]
+ [StringLength(100, ErrorMessage = "The name length should be lower than 30.")]
+ public ReactiveProperty Name { get; }
+
+ public ViewModel()
+ {
+ Name = new ReactiveProperty()
+ .SetValidateAttribute(() => Name);
+ }
+
+ public void DoSomething()
+ {
+ if (Name.HasErrors)
+ {
+ // 値が不正な場合
+ }
+ else
+ {
+ // 値が正しい場合
+ }
+ }
+}
+```
+
+### 初期検証エラーが不要な場合
+
+既定の動作では、`ReactiveProperty` は検証ロジックが設定されたときにエラーを通知します。
+初期検証エラーが不要な場合は、そのエラーをスキップできます。
+`Skip` メソッドを呼び出すだけです。
+
+```csharp
+class ViewModel
+{
+ // 検証属性を設定します
+ [Required(ErrorMessage = "The name is required.")]
+ [StringLength(100, ErrorMessage = "The name length should be lower than 30.")]
+ public ReactiveProperty Name { get; }
+
+ public ReadOnlyReactiveProperty NameErrorMessage { get; }
+
+ public ViewModel()
+ {
+ Name = new ReactiveProperty()
+ .SetValidateAttribute(() => Name);
+
+ // エラー メッセージの処理
+ NameErrorMessage = Name.ObserveErrorChanged
+ .Skip(1) // 最初のエラーをスキップします。
+ .Select(x => x?.OfType()?.FirstOrDefault())
+ .ToReadOnlyReactiveProperty();
+ }
+}
+```
+
+または、コンストラクターで `IgnoreInitialValidationError` フラグを設定します。
+
+```csharp
+class ViewModel
+{
+ // 検証属性を設定します
+ [Required(ErrorMessage = "The name is required.")]
+ [StringLength(100, ErrorMessage = "The name length should be lower than 30.")]
+ public ReactiveProperty Name { get; }
+
+ public ReadOnlyReactiveProperty