我试图创建一个C#的UWP(通用的Windows应用程序)应用程序。 我的问题是Frame
控制:如果我使用它,而NavigationCacheMode = Required
,每个用户可以追溯到时,页面不保存在内存中,并重新创建。 如果我设置NavigationCacheMode
到Required
或Enabled
,回到正常工作(没有新的页面对象), 但如果我从同类型导航到另一个页面,前一页对象被回收再利用(没有新的页面实例)。
所需的行为:
有没有办法有一个与原来以下行为Frame
控制(如Windows Phone中):
- 上创建新的页面实例
Navigate()
- 保持页面实例上
GoBack()
我所知道的唯一的解决方案是创建一个自己的Frame
控制,但是这会导致其他问题(如:缺少SetNavigationState()
方法,等...)
示例场景:
:用三页的简单应用实例TvShowListPage
, TvShowDetailsPage
, SeasonDetailsPage
。
-
TvShowListPage
是入门页面。 点击后TvShow
导航到TvShowDetailsPage
。 - 现在
TvShowDetailsPage
在列表中选择一个赛季并导航到TvShowDetailsPage
。 - 如果导航回,页面应该留在内存中,避免重新加载页面。
- 但是,如果用户可以追溯到
TvShowListPage
并选择另一TvShow
的TvShowDetailsPage
得到回收,并可能在错误的状态(例如显示投支点,而不是第一个,季节枢)
我在寻找默认的Windows Phone 7的行为:导航创建页面堆栈上一个新的页面,可以追溯到从栈中删除顶部页面,并显示从堆栈(存储在存储器)前一页。
解:
因为没有解决这个问题,我不得不重新实现所有分页相关类:页,框架,SuspensionManager等..
图书馆MyToolkit它提供了所有这些类可以在这里下载: https://github.com/MyToolkit/MyToolkit/wiki/Paging-Overview
参考文献:
- http://www.jayway.com/2012/05/25/clearing-the-windows-8-page-cache/ :没有很好的解决方案
- http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/88e6d1b3-1fa6-4ab4-a816-e77c86ef236f/ :一个自己的框架类的实现是无解的,因为它不与工作
SuspensionManager
Answer 1:
因为没有解决这个问题,我不得不重新实现所有分页相关类:页,框架,SuspensionManager等..
该解决方案可以在这里下载: https://github.com/MyToolkit/MyToolkit/wiki/Paging-Overview
更新:
页面类现在还提供了OnNavigatingFromAsync方法来显示例如异步弹出,如果需要取消导航...
Answer 2:
我有很多相同的问题。 我希望它这样,当我在地铁向前移动(Windows应用商店是正确的),它会创建一个新的实例。 然而,回去的时候,它会继续,我想保存数据。
所以,我也用NavigationCacheMode = NavigationCacheMode.Enabled。 我发现,无论哪种方式,我穿越的,向前或向后,一切都永远保存。 所以,我就往前走几页,然后退后一步等等。 希望一切都被重置为我向前,我总是发现那不是; 它保留数据。
我用尽了一切办法,包括写我自己的后退按钮的代码包括NavigationCacheMode = NavigationCacheMode.Disabled,但无济于事。 正如其他人所指出的那样,一旦启用它,在NavigationCacheMode根本不会禁用。
我没有找到一个解决方案。 我去了LayoutAwarePage.cs,只是做了一个微小的变化。 在“的OnNavigatedTo”我发现了一行:
// Returning to a cached page through navigation shouldn't trigger state loading
if (this._pageKey != null) return;
然而,评论违背了我想要的东西。 我是在一个单向模式寻找状态装载。 如果向前走,我想状态负荷; 如果向后移动,我想评论指示的行为 - 无状态负载。
所以我只是修改了行。
// Returning to a cached page through navigation shouldn't trigger state loading
if (this._pageKey != null && e.NavigationMode == NavigationMode.Back) return;
我测试了它和它完美的作品。 现在,向后导航时,它会记住的状态,从而保持页面相同。 向前导航,它加载新的。
也许不是最好的做法,但我不从我的代码隐藏来电“的OnNavigatedTo”。 我在做的一切“LoadState的。” 如果您正在覆盖在“的OnNavigatedTo”代码后,你可能会看到不同的行为。
谢谢,
约瑟夫·欧文
Answer 3:
当你向前导航,你可以设置NavigationCacheMode为禁用你打电话之前Frame.Navigate? 然后,在的OnNavigatedTo()重新设置NavigationCacheMode回Enabled。
这应该让这个当你向前导航,缓存被禁用。 但是,当你在新的页面实例到达,会的OnNavigatedTo再次启用它。 当你想导航回,你就不会调用Frame.GoBack之前触及NavigationCacheMode。 这应该给你的缓存实例,我想。
我相信这会工作,但我没有测试它。 我很好奇,想知道如果这样做。 有趣的场景出现。 我很乐意看到在行动应用程序,并更好地了解使用此行为。
Answer 4:
您可以使用NavigationCacheMode属性来指定是否在页面的一个新实例每次访问页面创建或如果已经被保存在缓存页面的以前构建的实例用于每次访问。
对于NavigationCacheMode属性的默认值是禁用。 在NavigationCacheMode属性设置为Enabled或当页面的新实例是不是每次访问重要的必需。 通过使用网页的缓存实例,可以提高应用程序的性能,并减少服务器上的负载。
设置NavigationCacheMode为Required意味着页面,无论是缓存在CacheSize属性指定的缓存页面的数量。 标记为所需要的页面不计算在总的CacheSize。 设置NavigationCacheMode为Enabled意味着页面缓存,但如果缓存页面数超过CacheSize的价值是有资格处置。
设置NavigationCacheMode属性为禁用,如果一个新的实例必须为每个访问创建。 例如,你不应该缓存,显示这是唯一的每个客户信息的页面。
所述的OnNavigatedTo方法被称为对于每个请求,甚至当页面被从缓存中检索。 你应该包括必须为每个请求执行的,而不是把这些代码在页面构造此方法的代码。
Answer 5:
我不得不得出一个page2
从我的类page
的类,然后当我想浏览到同一页的第二个版本,我发现如果this
对象是page
或page2
。 然后我浏览到page2
,如果我是在page
,然后导航到page
,如果在page2
。
唯一的缺点,这是一个巨大的一个,是,有没有办法从另一个派生一个XAML文件。 因此,所有的C#代码是在page
类代码隐藏符合市场预期,但也有两个几乎相同的XAML文件,一个为每个版本的网页。
一个小脚本很可能被添加为预生成步骤生成从第一第二页类,复制XAML数据和调整的类名称。
这是丑陋的,但它几乎完美的作品,我从来不用担心C#代码重复或怪异的导航缓存的问题。 我刚刚结束了有重复XMAL代码,这在我的情况真的从来没有改变,无论如何。 我也有两个警告结束了关于不使用的new
上自动生成的代码关键字page2.InitializeComponent()
和page2.Connect()
有趣的是,导航到page
,然后到page2
,然后到page
不会导致问题和二审page
类是无关的第一实际二审。
请注意,此解决方案是通过MS可能建议反对。
Answer 6:
我实现了这个由:
代码示例:
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));
}
}
这将是有益的,如果前进/后退按钮将不会使多大用处的。 作为这个解决方案会影响向前/向后导航。 如果您想使用向前/向后导航以及,然后一些额外的情况下,必须进行处理。
文章来源: WinRT/UWP Frame and Page caching: How to create new page instance on Navigate() and keep the page instance on GoBack()