Detecting dormant state and back navigation on WP7

Topics: UI Architecture
Oct 7, 2012 at 6:16 PM

I've used CM a few times for WPF/Silverlight projects but this is my first WP7 project.

I've had problems being able to detect when my ViewModel should be loading data under different scenarios.

For example I have a page that loads some random photos from a REST service on activation and shows the first one. However, I found it was being fired even if the page was being returned to because of a back navigation (which makes sense as it's being activated again). The same goes for returning from a dormant state.

I realise I could just use some logic to see whether I have any existing data loaded back from the StorageHandler class but that seems like a hack that works in this particular situation. I feel like I need more information about what is actually happening. Was the ViewModel being returned to from a back navigation? Or maybe a dormant state?

I know there is plenty of stuff on INavigationService but after playing around with it I couldn't get to a position where I was sure how my ViewModel was navigated to. This might just be my inexperience with the WP7 parts of CM, however.

There is a 'IsResurrecting' flag on IPhoneService but this obviously is just for detecting whether it is returning from being tombstoned. I found it was useful to me to also know if the ViewModel is being returned from a dormant state so I've made a fork and added a IsContinuing flag to IPhoneService. It works the same way as IsResurrecting (gets turned off just before Continued event fires).

I've also added a new interface for Screens/ViewModels called INavigate. This has two methods, NavigatedFrom and NavigatedTo. NavigatedTo also has a parameter to say whether the ViewModel is being navigated to as part of a back navigation. I didn't want to pass in NavigationMode from the event itself as it seemed dirty. I have the FrameAdapter looking for it and calling it just before Activate/Deactivate gets called.

I'm not totally happy about this interface. But it's obviously not in the Screen's inheritance chain like IActivate so it's optional.

I find I have a lot more context now about the different states going on so I can make a better decision about reloading data. I can do something like this:

public void NavigatedTo(bool backUsed)
{
    if (!this.phoneService.IsResurrecting && !this.phoneService.IsContinuing && !backUsed)
    {
        Coroutine.BeginExecute(this.GetImage().GetEnumerator());
    }
}

 So this data would only be reloaded on the first initial navigation.

Has anybody solved this type of problem in a better (simpler!) way? My fork is here is you're interested:

http://caliburnmicro.codeplex.com/SourceControl/network/forks/cshepherd/WP7DormantState