Crop WinRT / UWP and page caching. How to create a new page instance in Navigate () and save a page instance in GoBack ()

I am trying to create a UWP (Universal Windows App) application with C #. My problem is the Frame control: if I use it without NavigationCacheMode = Required , every time the user returns, the page is not stored in memory and will be recreated. If I set NavigationCacheMode to Required or Enabled , then the return works correctly (without a new page object) , but if I switch to another page of the same type, the previous page object is recycled and reused (there is no new page instance).

Desired behavior:

Is there a way to have the following behavior with the original Frame control (for example, on Windows Phone):

  • Create a new page instance in Navigate()
  • Store the page instance in GoBack()

The only solution I know is to create my own Frame control, but this leads to other problems (for example: missing SetNavigationState() method, etc.)

Example script:

A simple three-page application example: TvShowListPage , TvShowDetailsPage , SeasonDetailsPage .

  • TvShowListPage is the login page. After clicking on TvShow go to TvShowDetailsPage .
  • Now in TvShowDetailsPage select a season from the list and go to TvShowDetailsPage .
  • If you go back, the pages should remain in memory so as not to reload the pages.
  • But if users return to TvShowListPage and choose another TvShow , then TvShowDetailsPage returns to its original state and may be in the wrong state (for example, it shows the swarm arch, and not the first, seasonal turn).

I am looking for the default behavior for Windows Phone 7: Navigating creates a new page in the page stack, back removes the top page from the stack and displays the previous page from the stack (stored in memory).

Decision:

Since there was no solution to this problem, I had to override all the corresponding swap classes: Page, Frame, SuspensionManager, etc.

The MyToolkit library that provides all of these classes can be downloaded here: https://github.com/MyToolkit/MyToolkit/wiki/Paging-Overview

Literature:

+44
windows-8 windows-runtime xaml win-universal-app
Jul 18 2018-12-18T00:
source share
6 answers

Since there was no solution to this problem, I had to override all the corresponding swap classes: Page, Frame, SuspensionManager, etc.

The solution can be downloaded here: https://github.com/MyToolkit/MyToolkit/wiki/Paging-Overview

Update:

The page class now also provides an OnNavigatingFromAsync method to show, for example, an async popup and cancel navigation if necessary ...

+16
04 Oct
source share

I had the same problem. I wanted it so that when I moved to Metro (the Windows Store was correct), it would create a new instance. However, returning, he would save the data that I wanted to save.

So, I also used NavigationCacheMode = NavigationCacheMode.Enabled. I found that no matter what path I took, forward or backward, everything was always saved. So, I would go forward a few pages and then step back. Hoping that everything was reset when I moved forward, I invariably discovered that this was not so; he saved the data.

I tried everything, including writing my own feedback button code to enable NavigationCacheMode = NavigationCacheMode.Disabled, but to no avail. As others pointed out, after you turned it on, NavigationCacheMode just doesn't turn off.

I have found a solution. I went to LayoutAwarePage.cs and just made minor changes. In the "OnNavigatedTo" section, I found the line:

 // Returning to a cached page through navigation shouldn't trigger state loading if (this._pageKey != null) return; 

However, the comment contradicted what I wanted. I searched for state load in a unidirectional template. If you move forward, I need a state load; if moving backward, I wanted the behavior to point to a comment - there was no state loading.

So I just changed the line.

 // Returning to a cached page through navigation shouldn't trigger state loading if (this._pageKey != null && e.NavigationMode == NavigationMode.Back) return; 

I tested it and it works great. Now, when he moves backward, he remembers the state and keeps the page the same. Moving forward, it loads fresh.

It may not be best practice, but I do not call "OnNavigatedTo" from my code. I do everything through "LoadState". If you override "OnNavigatedTo" in code, you may see different behavior.

Thank,

Joseph Irwin

+8
Aug 30 2018-12-12T00:
source share

When you go ahead, can you set NavigationCacheMode to Disabled before you call Frame.Navigate ? Then in OnNavigatedTo () set NavigationCacheMode back to Enabled again.

This should make caching disabled when going forward. But when you arrive at the instance of the new page, OnNavigatedTo will turn it on again. When you want to go back, you will not touch NavigationCacheMode before calling Frame.GoBack . I think this will give you a cache instance.

I believe this will work, but I have not tested it. I would be interested to know, right. There is an interesting scenario. I would like to see the application in action and better understand the use of this behavior.

+6
Jul 18 2018-12-18T00:
source share

The NavigationCacheMode property is used to indicate whether a new page instance is created for each page visit or if a previously constructed page instance that has been cached is used for each visit.

The default value for the NavigationCacheMode property is disabled. Set the NavigationCacheMode property to Enabled or Required if the new page instance is not significant for each visit. Using a cached copy of the page, you can improve the performance of your application and reduce the load on your server.

Setting NavigationCacheMode in Required means that the page is cached regardless of the number of cached pages specified in the CacheSize property. Pages marked as "Required" are not counted in the total CacheSize. Setting NavigationCacheMode to Enabled means that the page is cached, but it has the right to delete if the number of cached pages exceeds the CacheSize value.

Set the NavigationCacheMode property to Disabled if you want to create a new instance for each visit. For example, you should not cache a page that displays information unique to each client.

The OnNavigatedTo method is called for each request, even when the page is retrieved from the cache. You should include in this code the method that should be executed for each request, and not put this code in the page constructor.

+1
Jul 18 '12 at 11:13
source share

I had to derive the page2 class from my page class, and then when I want to go to the second version of the same page, I find that this page or page2 , Then I go to page2 if I was in page , and go to page if in page2 .

The only downside, which is huge, is that there is no way to get one XAML file from another. Thus, all of the C # code is in the code of the page code as expected, but there are two almost identical XAML files, one for each version of the page.

A small script could be added as a pre-build step to generate a second page class from the first, copy XAML data and adjust the class names.

It's ugly, but it works just fine, and I never have to worry about duplicating C # code or weird navigation cache issues. I just get duplicate XMAL code, which in my case never really changes. I also get two warnings that you are not using the new keyword for automatically generated code for page2.InitializeComponent() and page2.Connect() .

Interestingly, switching to page , then to page2 , and then to page does not cause a problem, and the second instance of the page class is the actual second instance, not related to the first.

Please note that this solution is probably recommended for MS.

0
Oct 19 '15 at 23:24
source share

I have achieved this:

  • Setting NavigationCacheMode to Required / Enabled for required pages.
  • When you click the Page2 / link button:

    Turn the BackStack frame to see if page 2 is in the BackStack. If Page2 is found, you need to call Frame.GoBack () as many times as necessary. If not found, just go to the new page. This will work for any number of pages.

Code example:

 public void Page2Clicked(object sender, RoutedEventArgs e) { int isPresent = 0; int frameCount = 0; //traverse BackStack in reverse order as the last element is latest page for(int index= Frame.BackStack.Count-1; index>=0;index--) { frameCount += 1; //lets say the first page name is page1 which is cached if ("Page2".Equals(Frame.BackStack[index].SourcePageType.Name)) { isPresent = 1; //Go back required no of times while (frameCount >0) { Frame.GoBack(); frameCount -= 1; } break; } } if (isPresent == 0) { Frame.Content = null; Frame.Navigate(typeof(Page2)); } } 

This will be useful if the forward / back buttons are not heavily used. as this decision will affect forward / backward navigation. If you want to use fast forward / rewind, then some additional cases need to be handled.

0
Oct 21 '16 at 19:42
source share



All Articles