UWP: Back navigation

In Windows Universal app, when user has been navigated back, the top page at the navigation stack is being re-created again. That’s because a page itself is not kept in memory, when the user navigates forward to another page.

Let’s imagine an app. The first page of the app has a list. The user can scroll the list down and when he taps a list item, he has been redirected to the item details page. When the user presses back button, the main page is appeared. But the state of the page is not preserved. The user sees the same list with initial scroll viewer position. He has to scroll again to the item he left the page.

How to improve the described scenario to make the user happy? In our example, a developer has two options:

  1. Maintain ViewModel of the main page as Singleton and keep ScrollViewer vertical offset in the ViewModel;
  2. Enable UI cache for the main page.

I prefer the second one.

Navigation cache mode.

Page.NavigationCacheMode is the property, which allows a page to be stored in memory if the value of the property is set to Enabled or Required. In our case, the MainPage with enabled NavigationCacheMode, will be created once. Furthermore, the details page, with enabled navigation cache, is also created once and will be reused to show details of every data item. Thus, a page with NavigationCacheMode=Enabled stays in memory even the user navigates back or forward from the page.

Loaded EventTriggerBehavior and back navigation.

XamlBehaviors is a great library. It allows to get rid of event handlers in a page class and bind event handlers with commands exposed by ViewModel at XAML level. But be aware about using EventTriggerBehavior for Loaded event together with enabled NavigationCacheMode.

Let’s assume we have MainPage in our app with navigation cache is enabled:

 

In page XAML, there is EventTriggerBehavior which executes a command when the root element has been loaded. And a button, which navigates the user to another page, when it’s been clicked:

When the page is being loaded in the first time, LoadedCommand executes as expected. But what happens, when the user goes back from another page to the MainPage? If the user navigates back, Loaded event for the root Grid fires and I expect LoadedCommand to be executed as well. As you can guess, it doesn’t work in this way. When the user navigates back, EventTriggerBehavior is attached to the root element after the element has been loaded. So, for the described case, LoadedCommand never will be triggered.

For similar scenarios, it’s better to subscribe for FrameworkElement.Loaded manually and execute a command in code behind. Either, override Page.OnNavigatedTo and call your logic from there.

Fruitful coding!


Leave a Reply