tmori3y2のブログ

主にWindowsのプログラムなど

初心者が迷ったReactivePropertyを使用したView Modelの設計

ReactivePropertyは、

  • データソースのデータ型(DTO: Data Transfer Object)
  • それに毛(INortifyPropertyChanged)が生えた程度のPOCO (Plain Old CLR Object)

との相性が抜群な上、

Rxで処理を記述出来る

ので、複雑でない場合はView Modelでの実装が中心になります。

使用方法の詳細は、かずき大先生のこちらの記事が詳しいです。

通常のView Modelを実装する場合との比較もあるので、メリットが良く分かると思います。

blog.okazuki.jp

さて、ReactivePropertyの大きな特長は、

  • 通常、ModelやView Modelのクラス本体に実装されているINortifyPropertyChangedの実装パターンがプロパティクラスにカプセル化されていること
  • 通常、View Modelのクラス本体に実装されているINotifyDataErrorInfoの実装パターンがプロパティクラスにカプセル化されていること
  • INortifyPropertyChangedをObservableに変換できること
  • Observableであり、同時にObserverであること

が挙げられます。

INortifyPropertyChangedをObservableに変換できることにより、ModelからView Modelへの低コストで変換できるようになった結果、そこで型変換を行うコストも無視できるほど小さくなっています。

このため、ReactivePropertyの実装例では、TextBoxにバインドする数値型は文字列型に変換されているケースがほとんどです。

ここで、尾上大先生のスライド再び・・・

ugaya40.hateblo.jp

「コントロールの状態は信用しない。」

「バ​イ​ン​ド​す​る​オ​ブ​ジ​ェ​ク​ト​は​コ​ン​ト​ロ​ー​ル​の​状​態​ス​ト​ア​と​し​て​機​能​す​る」

TextBoxの状態ストアというなら、文字列しかあり得ない・・・

そういう意味でも、TextBoxにバインドする数値型のModelを、View Modelで文字列型に変換するのは理に適っている。

しかし、初心者はReactivePropertyを使用しないMVVMの実装例で良く有りがちな数値型をそのまま使うという例に惑わされ、同じ間違いを犯すことがあります。

その結果、空白や英字など数値にキャスト出来ない文字を入力した時に、View Modelに伝わる前にViewで例外が発生してしまい、Viewにエラー表示がされているものの、INotifyDataErrorInfoが実装されている筈のReactivePropertyでHasErrorsがtrueにならず、エラーが出ているのにデータソースへの保存などを許してしまうという失態を犯します。

ReactivePropertyを使用しないなら、以下の記事の方法で逃げる手もあるけど、ReactivePropertyは素直に文字列にしたら良い。

blog.okazuki.jp