首先看下Page的定义:
Page public class Page : UserControl { // // 摘要: // 获取或设置一个导航模式,该导航模式指示此 Page 是否已缓存和在时间段内缓存项是否应保持不变。 // // 返回结果: // 枚举的一个值。默认为 Disabled。 public NavigationCacheMode NavigationCacheMode { get; set; } } public enum NavigationCacheMode { // 摘要: // 从不缓存页面,每次访问时创建页面的新实例。 Disabled = 0, // // 摘要: // 缓存页面,并且每次访问时都重复利用缓存的实例,而不考虑帧的缓存大小。 Required = 1, // // 摘要: // 缓存页面,但当超过帧的缓存大小时放弃缓存的实例。 Enabled = 2, }
默认情况下它是Disabled,下面是这种情况的演示:
a) 有2个Page(Page 1, Page 2),Page 1会通过http请求数据并显示到ListView中,
b) 点击Page 1页面的Next Page按钮,会跳转到Page 2页面。
c) 点击Page 2页面的Back按钮,会返回到上1个页面,
d) 这时ListView的数据消失了。
倘若将NavigationCacheMode设置为Enable/Required,就不会出现问题。但是这样一来却带来新的问题:
假设我们现在有A1/A2/A3这样3个页面,点击都会进入B页面,我们希望从A1/A2/A3进入到B页面显示不一样的数据,结果你会发现却事与愿违,每次都显示相同的数据,因为第1次进到B页面时数据就会被缓存起来,以后每次进入时都显示之前缓存的数据。
如何解决这些问题呢?
在用VS2012创建项目时,它会给我们生成LayoutAwarePage这样一个Page,它提供了以下2个方法用于保存/恢复数据。
/// <summary> /// 使用在导航过程中传递的内容填充页。在从以前的会话 /// 重新创建页时,也会提供任何已保存状态。 /// </summary> /// <param name="navigationParameter">最初请求此页时传递给 /// <see cref="Frame.Navigate(Type, Object)"/> 的参数值。 /// </param> /// <param name="pageState">此页在以前会话期间保留的状态 /// 字典。首次访问页面时为 null。</param> protected virtual void LoadState(Object navigationParameter, Dictionary<String, Object> pageState) { } /// <summary> /// 保留与此页关联的状态,以防挂起应用程序或 /// 从导航缓存中放弃此页。值必须符合 /// <see cref="SuspensionManager.SessionState"/> 的序列化要求。 /// </summary> /// <param name="pageState">要使用可序列化状态填充的空字典。</param> protected virtual void SaveState(Dictionary<String, Object> pageState) { }
1# 当从A页面进入到B页面时,A页面的SaveState方法会被调用,这时我们就将数据放到pageState字典中,
2# 当从B页面返回到A页面时,A页面的LoadState方法会被调用,这时我们从pageState中取出数据,将数据渲染到页面上。
在实际开发中,我还遇到这样一个问题,当GridVeiw数据很多时,用户很可能滑动GridView,这时我们还需要记录GridView滑动的距离,以便在页面返回时显示用户上次滑动到的位置。这里有1个工具类,感谢这位前辈:http://www.cnblogs.com/webabcd/
XamlHelperpublic class XamlHelper { /// <summary> /// 获取指定元素所占用的矩形区域,此矩形的位置相对于屏幕原点 /// </summary> public static Rect GetElementRect(FrameworkElement element) { GeneralTransform generalTransform = element.TransformToVisual(null); Point point = generalTransform.TransformPoint(new Point()); return new Rect(point, new Size(element.ActualWidth, element.ActualHeight)); } /// <summary> /// 获取指定元素内部的指定类型的 DependencyObject /// </summary> public static T GetVisualChild<T>(DependencyObject parent) where T : DependencyObject { T child = default(T); int numVisuals = VisualTreeHelper.GetChildrenCount(parent); for (int i = 0; i < numVisuals; i++) { DependencyObject obj = (DependencyObject)VisualTreeHelper.GetChild(parent, i); child = obj as T; if (child == null) child = GetVisualChild<T>(obj); if (child != null) break; } return child; } /// <summary> /// 获取指定元素内部的指定名称的 FrameworkElement /// </summary> public static T GetVisualChild<T>(DependencyObject parent, string name) where T : FrameworkElement { T child = default(T); int numVisuals = VisualTreeHelper.GetChildrenCount(parent); for (int i = 0; i < numVisuals; i++) { DependencyObject obj = VisualTreeHelper.GetChild(parent, i); child = obj as T; if (child == null || child.Name != name) child = GetVisualChild<T>(obj, name); if (child != null) break; } return child; } /// <summary> /// ensure unsnapped /// </summary> public static bool EnsureUnsnapped() { bool unsnapped = ((ApplicationView.Value != ApplicationViewState.Snapped) || ApplicationView.TryUnsnap()); return unsnapped; } }
获取GridView水平滑动的距离:
double hOffset = XamlHelper.GetVisualChild<ScrollViewer>(gridView).HorizontalOffset;