かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

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); }
    }
}