Bryan Taylor
Bryan Taylor

Reputation: 149

Universal Windows App C# - Cache an instance (and state) of a page when navigating to a new instance of the same page

Hi StackOverflow Community,

I am working on a universal app for Windows in C# and XAML. So far, progress has been smooth (the whole framework is very easy to use) however I have run into an issue related to page navigation and state caching that I was hoping to get some help with.

In a standard template, navigation through an app would look like this: Home -> Profile (ID 1) -> Game (ID 120) -> (Back) Profile (ID 1) -> (Back) Home -> Profile (ID 2) -> Game (ID 210)

However, I'd like to do something like this: Home -> Profile (ID 1) -> Profile (ID 2) -> Profile (ID 3) -> Game (ID 120)

The reasoning behind this requirement is simple: the profile page contains a list of friends, groups, games, etc for that profile. Clicking on a friend should bring you to their profile page and from there you should be able to view their details, their friends, etc and continue to drill down friends lists or groups (which can link back to profiles).

This is important, since most of the questions I've come across on SO have been related to this... but I am already able to navigate back and forth through the list properly like I listed in the second example. The issue that I'm having comes from some funny caching and state issues during navigation.

For simplicity sake, lets just talk about the Windows Phone view; the Profile Page contains a Pivot Table with four sections (Details, Games, Friends, Groups). If I'm on the profile for user 1, swipe over to the friends section, and tap on the profile for user 2 then the navigation occurs and I have 3 pages in my back stack (home, profile for user 1, profile for user 2). This is not the part I'm having trouble with; the issue I'm having is related to navigating backwards - when I hit the back button and navigate backwards on the frame I am returned to the profile for user 1 (which is good), however the state of the view is reset and instead of being on the 'Friends' section I am returned to the first section (in this case the 'Details' section - which is annoying from a UX perspective).

I have played around with the NavigationHelper and the SuspensionManager as well as experimented with setting the page caching to enabled, however I got some unexpected results. As explained above if I don't set the NavigationCacheMode to Enabled then I am always returned to the first pivot section when I navigate backwards, however if I DO set the cache mode to Enabled then when I navigate to new instances of the profile page then the state seems to be recycled and instead of appearing on the 'Details' section for the NEW profile, I am loaded into the same section I was in when the navigation occured (i.e. if I was on the 'Friends' section for User 1, then when I tap User 2 I will be on the 'Friends' section for User 2. Also annoying from a UX Standpoint). The same will occur when I'm navigating backwards as well, if I'm 4 profile deep and looking at the 'Groups' section for profile 4, when I hit back then I will be looking at the Groups' section for profile 3 (even if I navigated from profile 3 -> profile 4 from the 'Friends' section)

Is this something that any of you have experienced? I'm not looking for code snippets specifically (though I definitely am not in the habit of turning them down!), but more just the thought process on how I should handle this. I know that some apps do something similar to this, and I'm sure I'm missing something small but any advice would be greatly appreciated.

An example of this same type of navigation I'm trying to achieve would be on the Hulu App. If you select a series and swipe over to the 'Recommended' Section you will see other shows. Tapping on one of these shows will open up the details for that show (and you can go multiple layers deep), however tapping the back button will bring you back to the last series you viewed (and most importantly, will also put you back on the 'Recommended' Section)

Normally I would absolutely provide code-snippets, but since this is more of a broad question rather than a "Why doesn't my code work?" question I decided hold off and will wait to provide snippets only if they are requested.

Thanks in advance!

Upvotes: 2

Views: 967

Answers (1)

Kai Brummund
Kai Brummund

Reputation: 3568

Page Caching has gotten a lot more flexible but also a lot more complex in Windows Store Apps. You now have the flexibility to implement navigation patterns like yours, but you also have to do a lot of stuff by hand.

First there is NavigationCache: You can enable it on pages (but ONLY in the constructor). For the Cache to work correctly you also have to set the CacheSize (it is in the default App.xaml.cs and set to 1. You will have to increase it to work properly.

Still, it only keeps one instance of the page in the cache. In your case, you navigate to that page multiple times with different IDs. With navigation cache enabled, it will just make sure the all land on the same instance of the page.

I usually only cache the root page of my app and only if it contains a lot of data (like your hub).

NavigationCache if used to often fills up a lot of memory and therefore your app gets shut down earlier when put in background. Use it with care.

Usually it is best to just reconstruct pages every time you navigate to them and just cache the data (if obtained over the wire).

The NavigationHelper offers a simple standard implementation for saving a state dictionary for a page. When your page gets recreated on a back navigation, you still have to handle it your state by hand.

It just provides you with a dictionary where you can save values in: What HubSection you are in, how far you scrolled, etc.

It utilizes the BackStackDepth to get you the right dictionary for the page you are on.

Once you get your dictionary back, you have to set the HubSection, scroll down, etc.

So in the end: Yes, you have to do all that by hand...

Upvotes: 2

Related Questions