0
votes

Suppose my page hierarchy is

AViewModel->BViewModel

In every ViewModel (registered as PerRequest) I load the data from server in the OnActivate method and set a flag (private bool class variable) that the data is loaded.

In Windows Phone 8 and Windows Phone 8.1 Silverlight, when the user navigates back from BViewModel, the AViewModel, then in OnActivate the ViewModel knows that the data is already loaded (the flag is true) and does nothing.

This does not work in Windows Phone 8.1 because each time the user navigates back, the ViewModel is created again (I can see the constructor call).

When I set NavigationCacheMode=NavigationCacheMode.Required; in all the views, then the flag survives the back navigation. The problem with this solution is that when I navigate back from BViewModel back to AViewModel, the flag lives so the data is not loaded again but (that is ok) but when I then navigate to BViewModel (with different parameter), then nothing happens because BViewModel was not destroyed and it is reused, with the flag saying that data does not need to be loaded.

Is there a way to make it behave exactly like in Windows Phone 8 (or 8.1 Silverlight)

1
Can you check the type of navigation (back, forward)? Can you store another variable in BViewModel which holds the old parameter (just id?) which you can compare (and not just check the bool) when navigating to? - Igor Ralic
storing all the navigation parameters somewhere and then comparing all of them with the new ones should work, but I hope there is an easier way, this can produce errors - Igor Kulman

1 Answers

2
votes

Looks like the key to this problem is to know if a page (ViewModel) was activated by navigating back (with the back button) or not. I came up with a solution that seems to work but is not very elegant.

I created a bool property on the App class

public bool IsBackNavigation { get; private set; }

which I set in the framesNavigating` event

frame.Navigating += (s, e) => IsBackNavigation = e.NavigationMode == NavigationMode.Back;

The ViewModel can then access it as

(App.Current as App).IsBackNavigation

This solution seems to work with NavigationCacheMode=NavigationCacheMode.Required (or alternatively NavigationCacheMode=NavigationCacheMode.Enabled).

However I am a bit afraid of the automatic caching, a solution with a frame that does the same thing as in Windows Phone 8 would be preferable.

There is a discussion about this issue at Github: https://github.com/Caliburn-Micro/Caliburn.Micro/issues/51