首先看下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)
{
}
我们可以让自己的Page继承于LayoutAwarePage,然后重写上面这两个方法。
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;