かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

ReactivePropertyとPrism for WinRTとの連携

ちょっとしたTipsですが…。

Prism for WinRTとReactivePropertyを同時に使う場合以下の点に気を付けるといいです。

なるべくコンストラクタインジェクションを使う

ReactivePropertyは、コンストラクタで組み立てるのが一番スムーズなので出来るだけ外部からDIするものはプロパティでインジェクションするのではなくて、コンストラクタでインジェクションしましょう。そうすると、コンストラクタで準備万端状態になるので、ReactivePropertyの組み立てがスムーズに行えます。

どうしてもプロパティインジェクションしたいときなど

どうしてもプロパティでDIしたいときや、ナビゲーションのタイミングで初期化したいものなどがあるときも、以下の方法で、やるとコンストラクタでReactivePropertyの組み立てができます。

DIで使うプロパティもPropertyChangedイベントを発行する

こうしておくとObservePropertyを使って監視できるのでコンストラクタでさくっといけるようになります。

public Hoge()
{
  // DI対象のプロパティが全部設定が終わったら初期化する
  var initCompleted = Observable.Merge(
    this.ObserveProperty(o => o.DIProp1).Where(v => v != null),
    this.ObserveProperty(o => o.DIProp2).Where(v => v != null))
    .Skip(1) // もっといいやり方ありそう…
    .Subscribe(_ =>
    {
        // ここで初期化
    });
}

サスペンド対応

サスペンド時にReactivePropertyの値を保存したいときは、リストアしたくないReactivePropertyにIgnoreDataMember属性を付けたうえで、以下のようなプロパティをViewModelに定義しておくといい感じにしてくれます。

public class MainPageViewModel : ViewModel
{
    // リストア対象のReactiveProperty
    public ReactiveProperty<string> Input { get; private set; }

    // リストア対象外のReactiveProperty
    [IgnoreDataMember]
    public ReactiveProperty<string> Output { get; private set; }

    // Prism for WinRTのリストアの仕組みに乗せるためのプロパティ
    [RestorableState]
    public string PackData
    {
        get { return SerializeHelper.PackReactivePropertyValue(this); }
        set { SerializeHelper.UnpackReactivePropertyValue(this, value); }
    }
}