4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

BooleanNotifierをToReactiveCommandしたときの挙動、が思っていたのと違う理由

Last updated at Posted at 2020-12-21

概要

この記事は以下の記事へのアンサーというか、私なりの推測をしたものです。

【WPF】BooleanNotifierをToReactiveCommandしたときの挙動について【ReactiveProperty7.5.1】

BooleanNotifierの挙動が思っていたのと違う?

同じ初期値falseを持つBooleanNotifierとReactivePropertyからReactiveCommandを生成するとCanExcuteの値が異なります。

var booleanNotifier= new BooleanNotifier(initialValue: false);
var reactiveProperty = new ReactiveProperty<bool>(initialValue: false);

BooleanNotifierButtonCommand = booleanNotifier.ToReactiveCommand();
ReactivePropertyButtonCommand = reactiveProperty.ToReactiveCommand();
//BooleanNotifierButtonCommand.CanExcute == true;
//ReactivePropertyButtonCommand.CanExcute == false;

コード的原因

コード的には元記事でも述べられているように、以下のところがまさに原因です。

(BooleanNotifierにはなく、ReactivePropertyでのみ)Subscribeの中でOnNext()が記述されている

でもなんで?(本題)

ここからが記事の本題ですが、では何故BooleanNotifierはそうしないのか?という疑問があるかもしれません。

それは実はSubscribeされたらOnNextをするReactivePropertyのほうが、Rx的にもしくはObserverパターンとしては異質なことをしているから、です。

Rx入門 (2) - オブザーバーパターン

Observerパターンの説明では通常、Observerが購読(Subscribe)した直後に値が流れて来ることはなく、Observableが通知(OnNext)して初めて値がObserverに来ます。

しかし、ReactivePropertyでは異なる動きをします。これはMVVMパターンの中で使われる上でそのほうが便利だからです。それは前述のToReactiveCommand()でもそうですし、あるReactivePropertyから別のReadOnlyReactivePropertyに変換する場合もそうです。この動きはReactivePropertyのModeRaiseLatestValueOnSubscribeを無効にすれば無くすこともできます。

ただ、この判断には躊躇いもあったようで、途中で破壊的変更をして導入されています。

ReactivePropertyのデフォルトモードが DistinctUntilChanged|RaiseLatestValueOnSubscribe になりました。今まではRaise…が入ってなかったのですが、思うところあって変わりました。例えばCombineLatestは、全てが一度は発火していないと動き出しません。ReactiveCommandの条件に使うなどの場合にRaiseしてくれないと不都合極まりなく、かつ、Subscribeと同時にRaiseすることによる不都合なシーンは逆に少ない。ことを考えると、必然的にデフォルトをどちらに振るべきかは、分かりきった話でした。

というわけで、BooleanNotifierがReactivePropertyと違う挙動をするのは、ReactivePropertyがMVVMパターンを意識して本来のObserverパターンとは違う挙動をするようなクラスだから、です。

じゃあ、BooleanNotifierはどう使うか、というと本来のObserverパターンらしく何かの変更通知です。ロギングやバックアップ処理など、Viewに現在の状態を常に示す、という以外の用途ですね。

余談

実は同じNotifier系でもBusyNotifierはSubscribeされたらOnNextします。これはToReactiveCommand()などで使われることが想定されたクラスだからです。
https://blog.okazuki.jp/entry/2016/04/09/005825

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?