2
Vote

VisualStateAwarePage page state is broken for cached pages

description

Suppose we have a VisualStateAwarePage instance with NavigationCacheMode set to Enabled or Required. The first time this page is navigated to, a session state entry is created with key "Page-n" where n is equal to the current back stack depth (see the OnNavigatedTo() method of the VisualStateAwarePage class). If this page is navigated to again, then a new session state entry is not created, and the old page state dictionary is reused with the previous key "Page-n". The problem is, in my app, this particular cached page can exist in many different positions in the back stack.

Here's an example "backstack" (leftmost DetailsPage is the current page at time of app termination).
DetailsPage [Page-1] <- PreviewPage [Page-2] <- DetailsPage [Page-1] <- FirstPage [Page-0]

Here, the DetailsPage instance is cached, and different data is displayed for this page in the first and third back stack slots (i.e. the navigation parameter is different for those entries). All is good when the DetailsPage is displayed for the first time, but when it is displayed again it reuses the previous page state entry "Page-1" instead of "Page-3". When the app terminates, the session state dictionary is saved to storage. Then when the app is launched, the saved session state is loaded from storage and the frame navigation state is restored (see SessionStateService.RestoreFrameNavigationState()). This causes the OnNavigatedTo() method of the DetailsPage to be called, where it sets the _pageKey to "Page-3", which is correct for a non-cached page, but in fact the correct key should be "Page-1". This causes a KeyNotFoundException (since the page key doesn't exist in the state dictionary), and then the exception is caught silently in MvvmAppBase without giving the navigation service a chance to restore the saved navigation. This leaves the DetailsPage in an inconsistent state (the OnNavigatedTo() method of my DetailsPageViewModel isn't called).

comments