Clearing the page cache in Windows 8 Metro apps

In Windows 8 Metro apps, the navigation model has been improved over the previous one found on Windows Phone. One difference is that page caching has to be manually enabled for each page, as we explained in part 8 of our Windows Phone to Windows 8 conversion series. And, the page cache is active for both forward and backward navigation, which recently gave me some headaches. The solution is to clear the cache when backing away from the page, and forcing other pages to always be cached.

Activating page caching

Activating the page cache is as easy as setting the NavigationCacheMode property

in the constructor of the page.

The problem

What gave me problems was navigating back from a page and then forward to it again. The system was keeping the page cached anyway and I had some weird behavior such as the back button being in it’s hover state instead of neutral. Also the SemanticZoom control on the page would sometimes not show any items at all.

The solution – clearing the cache

So, I wanted to have the cache enabled for the page when returning to if from a page further down the stack – but have the page removed from the cache when backing away from it. I could not find a way to manipulate the contents of the cache, so instead I went with clearing the cache instead.

There is no direct method to clear the cache, but you can set the size of the cache. So, when backing away from the page in question, I execute this code

What to watch out for

Of course, clearing the cache will clear all the pages from the cache, not just the page in question. To force the other pages that I wanted to keep cached to survive the cache clearing – I instead set those to

which is the stricter form of caching. This will cause the page not be put the page cache that the user controls the size of, but to be cached elsewhere, hence be immune to my clearing of the cache.

Setting some pages to NavigationCacheMode.Required and clearing the cache when backing away from a single page is of course not a clean cut solution, but it works for me here. The app I’m working on fairly small and the other pages work well with this scenario. For a larger app I would probably go for fixing the page that did not behave well instead of impacting all other pages.

Worth mentioning is that I tried to set NavigationCacheMode.Disabled when navigating away from the page, but that did not stop it from being cached. I guess that once it’s been put in the cache it is not taken away by just setting the property again.

Happy coding, ciao!

This Post Has 21 Comments

  1. Hello.

    Thank you for sharing this piece of code! Do you know if there is a way to clear the navigation-cache in metro javascript applications?

  2. I’m having problems implementing this… “Parent” is null

    1. Are you in a Page that is set as the content of a Frame?

      Where do execute the code, a system callback (e.g. NavigatedTo)?

      You’re welcome to post your code :)

  3. What you meant by if (e.NavigationMode == NavigationMode.Back).

    Thanks.

  4. @Smith We only want to clear the page cache when navigating back to a page (=we’ve just left the lower-level page and the data on that page should not be cached)

  5. I everyone am using xaml C# for Metro app . there i am using one UserControl for Flyout in that flyout i need to have caching .how can i get this . please help me out to find solution for this . thank in advance .

  6. Thanks Andreas ;)
    Even after two years, a simple piece of code to effectively clear the navigation cache is still useful

  7. Thank you for the nice article and your suggestion saved me many hours of work!

  8. Great article! Saved me a lot of headache.

    @Ivan, There may have been some changes since Windows 8.1. this.Parent was always null for me, but there is a this.Frame property that seems to do the trick perfectly. I’ll be keeping my eye on this to make sure there aren’t any ill effects, but I only have a few of my Pages that need caching/clearing.

    Code:
    private void ResetPageCache()
    {
    //I haven’t seen this be null, but I imagine it could be.
    //I’d rather have the cache stick than the app crash.
    if (this.Frame == null) { return; }

    var cacheSize = this.Frame.CacheSize;
    this.Frame.CacheSize = 0;
    this.Frame.CacheSize = cacheSize;
    }

  9. Hello my friend, I don’t understand this line:
    this.Frame.CacheSize = cacheSize;
    Could you explain to me?

    1. Hi!

      Well, the three lines are connected:
      var cacheSize = ((Frame) Parent).CacheSize;
      ((Frame) Parent).CacheSize = 0;
      ((Frame) Parent).CacheSize = cacheSize;

      The cacheSize variable just holds the old value while the cacheSize is temporarily set to 0 to clear stuff out.

      Clearer?

  10. Thank a lot you for the nice article. You saved me many hours !!!

  11. It is too easy.
    Just use below code on page leave:

    this.NavigationCacheMode = NavigationCacheMode.Disabled;

    And use below code on page constructor:

    this.NavigationCacheMode = NavigationCacheMode.Enable;

    1. Hi Mohammad,

      Yep, you are right – that’s the way to do it these days.

      You often want to wrap the “on page leave” in:

      override OnNavigatingFrom(.. e)
      {
      if (e.NavigationMode == NavigationMode.Back)
      {
      this.NavigationCacheMode = NavigationCacheMode.Disabled;
      }
      }

      since you want the page to stay in the cache when navigating forward from it

  12. Andreas,

    I have a problem clearing the cache.Basically it doesn’t work. I have added the above code on the page from which the cache needs to be reset, however it doesn’t. In my case, Navigation.new/forward/refresh. i need to reset the cache

    protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
    {
    base.OnNavigatingFrom(e);
    if(e.NavigationMode == NavigationMode.New || e.NavigationMode == NavigationMode.Forward || e.NavigationMode == NavigationMode.Refresh)
    {
    ResetPageCache();
    }
    }

    private void ResetPageCache()
    {
    var cacheSize = ((Frame) Parent).CacheSize;
    ((Frame)Parent).CacheSize = 0;

    }

    Even the above line or peice of code did not reset the cache in my applicaiton.

    I need to reset the cache everytime i hit the home button or refresh button unfortunately all my cache since the root page are intact. Could you please offer me a suggestion of where could have went wrong.

    For my forward/home/refresh button.I always navigate using this.Frame.Navigate(typeof(MainPage));

    However for My back button, i use one that came along with native xaml code.

    1. Hi Natty,

      Are you writing an app for Windows 8 or Windows 10 (UWP). If the latter – there are better ways of doing it, please see my reply to a comment below.

      (search for “NavigationCacheMode.Disabled”)

Leave a Reply

Close Menu