WP7 Developer Blog : 解决WP7应用中循坏导航的问题
原文:Solving Circular Navigation in Windows Phone Silverlight Applications
Non-Linear Navigation Service 是我们最新发布的方法。Windows Phone recipes 是一系列开源工程(MSPL)的集合,为了帮助windows phone 社区编写程序。recipes面向一些特定主题编写通用模型,想法是提供重用代码,这样在很多场合改改就能够适用。程序员一定很高兴看到并使用他们。
回到主题- Non-Linear Navigation Service 是一套通用模式,它适用于WP7 Silverlight 应用,让应用的不同页面循环导航。应用程序的顺序导航有些像把每个特性页面的拷贝放到堆栈,然后顺序呈现实现回退。WP7 Silverlight模型就像很多页面批量组成的模组,大多应用都是多页面(WindowsPhonePage类型)包含在一个框架下面(WindowsPhoneFrame类型),开发者能够让用户导航到一个新页面,用户可以选择前进或者回退。每一个应用,WP7会保持一个堆栈记录用户的访问历史。在现在的版本中,你没有任何API改变这个堆栈。
开发者能够调用NavigationService.Navigate方法到特定页面,但是页面堆栈是个问题。例如,你已经有了包含多页面的导航,这时候你可以如下图操作记录堆栈:首先从首页面到页面2,之后到页面3,之后回到主页面,这是我们理想的状态。
从体验来说,用户厌倦连贯性。用户从首页直接到页面3,但是现在,当用户按回退键时会怎么?我们当然希望是回到首页,是么?但是依照堆栈规则,你的页面会按照之前的堆栈记录回退页面2,这就让用户感到困惑,在用户希望一个特定的导航时,因为堆栈(Navigation Loop),回退键的功能被改变。
从技术的角度看,Navigation Loop是页面实例形成的堆栈,我们希望能够消除堆栈从而终止Loop。在这里你可以更多了解导航,非线性导航(Non Linear Navigation)
Note: UX 指南建议不要在应用中创建 Home 功能,这是导航的第一设计要点,即便如此,你也会在顺序导航进行的时候中止。
有很多方法解决问题,比如使用smart UI,弹出窗口或者使用context menu。但是,很多时候你也没有办法,必须包含一些特性页面。既然不能操作堆栈,你不得不需要清除页面堆栈(请查看 Windows Phone navigation works)
现在,唯一的方案是执行递归导航。递归导航随着会随着堆栈自动执行,直到回到首页终止Loop.要实现这些,你需要做如下:
1. 追踪导航历史来确认结束循坏的可能
2.一旦确认终止,设置“递归”标记,之后调用NavigationService.GoBack()方法
3.在每个页面,通过OnNavigationTo()方法察看”递归”标记,如果有重新回到主页
还好我们解决了问题。在初始化时,NonLinearNavigationService会检控你的导航。当探测到navigation Loop时,他会自动执行递归。我们不需要做额外的工作,只需要在初始化插入下面的代码片断:
// init the non-linear nav service, make sure you call it last in the app CTOR NonLinearNavigationService.Instance.Init(RootFrame); NonLinearNavigationService.Instance.Init(RootFrame);
在这之后,你可以继续使用 Navigate ()方法,NonLinearNavigationService会解决其他。你可以到导航到任一页面, NLNS能够为你屏蔽堆栈的影响,但是还有一些限制需要在使用时注意:
- NLNS不允许你创建Loop Navigation,即时你想也不可能- 如果Loop 是你应用的特定场景,不要使用NLNS.
- 如果程序使用了Bar, 你需要在OnNavigatedForm() 方法中手动隐藏它,避免在递归返回时闪屏。同时,NonLinearNavigationService()会设置RootFrame时选择transparent,需要格外注意App Bar。
- 在取消导航请求时,Back button Bug 会出现,如果需要处理这个事件,可以加入下面的代码(通常在 OnNavigationForm()方法中)
protected override void OnBackKeyPress
(System.ComponentModel.CancelEventArgs e)
{
base.OnBackKeyPress(e);
if (NavigationService.CanGoBack)
{
e.Cancel = true;
NavigationService.GoBack();
}
}
强烈推荐你来阅读NonLinearNavigationService 文档 ,帮助更好的理解问题和方案,同时也包含关于recipe的一些背景信息。
在这里下载 NonLinearNavigationService