読者です 読者をやめる 読者になる 読者になる

かずきのBlog@hatena

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

PrismのViewModelでイベントの購読解除などの後始末をするタイミング

PrismのViewModelには画面遷移してきたタイミングで呼ばれるOnNavigatedToと画面から離れるときやサスペンド時に呼ばれるOnNavigatingFromメソッドがあります。ページが有効な間はイベントを購読したいというケースでは、OnNavigatedToでイベントの購読を行い、OnNavigatingFromで購読解除すると一見よさそうに見えます。

デバッガをアタッチしてる状態では、それでいいのですが、デバッガをアタッチしてない状態では画面を最小化したり電話でバックグラウンドに回した時に、実はOnNavigatingFromがsuspending引数がtrueになって呼び出されます。サスペンドからの復帰時にはOnNavigatedToは呼ばれないという厄介な状態になります。(完全にアプリが終了されたら起動シーケンスからやり直しなので呼ばれますが)

なので、OnNavigatingFromで無条件に購読解除すると、サスペンドからの復帰時にイベントの処理が動かないという状況になったりします。これを回避するには以下のように、suspendingがfalseの時だけイベントの購読解除をするといったような処理が必要になります。

public override void OnNavigatedTo(NavigatedToEventArgs e, Dictionary<string, object> viewModelState)
{
    base.OnNavigatedTo(e, viewModelState);

    // ここでイベント購読
}

public override void OnNavigatingFrom(NavigatingFromEventArgs e, Dictionary<string, object> viewModelState, bool suspending)
{
    base.OnNavigatingFrom(e, viewModelState, suspending);

    if (!suspending)
    {
        // ここでイベント購読解除
    }
}

ちょっとはまった。