导航重定向Redirecting an initial navigation

转自:http://www.devdiv.com/forum.php?mod=viewthread&tid=71730&extra=page%3D1%26filter%3Dtypeid%26typeid%3D305%26typeid%3D305

 

 

One more post on the subject of keeping screens out of the backstack. A common scenario we see is a variation of thelogin screen scenario I mentioned the other week. In this case, the first page the user is supposed to see depends on some state saved in by the application (maybe a user preference for which screen to see first, or maybe based on trial mode, etc.) and whilst you want that first page to be in the back stack (ie, it is alegitimate place) you don’t want any additional “landing pages” taking up a slot in the backstack. Another situation where this arises is if your application is extending the Music + Videos hub or isregistered as a Photo Extension and you need to show a different page when launched from these experiences.

There are (at least) two ways of doing this; I’ll present two of them here along with a sample app that shows them in action. For my simple example, the trigger for showing a particular page is going to be whether the current time has an even or odd number of seconds (this is a silly example, but makes it easy to test both startup cases). In a real application the trigger might be based on incoming parameters, settings stored in IsoStore, etc.

Cancelling Navigation

The first way to change your initial page is to cancel the incoming navigation to MainPage.xaml and then fire off the desired navigation instead. This is easily done in a few lines of code; firstly, at the end of theApp constructor we add an event handler to the Navigatingevent:

  RootFrame.Navigating += new NavigatingCancelEventHandler(RootFrame_Navigating);

In the event handler, we do several things. First, we check if the navigation is to MainPage.xaml (theNavigationPage specified in the WMAppManifest.xml file) and if not, we bail:

  // Only care about MainPage
  if (e.Uri.ToString().Contains("/MainPage.xaml") != true)
    return;

Next we perform a simple check to see which page to load (in this case, are the seconds odd or even?), but this is where you’d do your own logic for switching pages:

  // Our dummy check -- does the current time have an odd or even number of seconds?
  DateTime time = DateTime.Now;
  int seconds = time.Second;
  bool isOdd = (seconds % 2) == 1;

Finally we kick off a navigation to the desired page, being careful to avoid overlapping navigations (which will fail):

  // Cancel current navigation and schedule the real navigation for the next tick
  // (we can't navigate immediately as that will fail; no overlapping navigations
  // are allowed)
  e.Cancel = true;
  RootFrame.Dispatcher.BeginInvoke(delegate
  {
    if (isOdd)
      RootFrame.Navigate(new Uri("/odd.xaml?method=cancel%20navigation&time=" + time.ToLongTimeString(), UriKind.Relative));
    else
      RootFrame.Navigate(new Uri("/even.xaml?method=cancel%20navigation&time=" + time.ToLongTimeString(), UriKind.Relative));
  });

Using UriMapper

The second method you can use is based on the UriMapper class, which is a standard part of the Silverlight 3 navigation framework.UriMapper was slightly easier to use in the Mix-era CTP when we set theRootVisual of the application to a frame inside of App.xaml, but it’s still easy to do with the new delayed approach. First of all we add a newUriMapper to the Resources section of App.xaml:

  <!--Simple UriMapper that will be programmatically updated to point to the right page at runtime—>
  <UriMapper:UriMapper x:Name="mapper">
    <UriMapper:UriMapping Uri="/MainPage.xaml" />
  </UriMapper:UriMapper>

Then instead of handling the Navigating event (as before), we simply attach theUriMapper to the RootFrame …

  // Get the UriMapper from the app.xaml resources, and assign it to the root frame
  UriMapper mapper = Resources["mapper"] as UriMapper;
  RootFrame.UriMapper = mapper;

and re-write the rule for MainPage based on the desired page:

  // Update the mapper as appropriate
  if (isOdd)
    mapper.UriMappings[0].MappedUri = new Uri("/odd.xaml?method=UriMapper&time=" + time.ToLongTimeString(), UriKind.Relative);
  else
    mapper.UriMappings[0].MappedUri = new Uri("/even.xaml?method=UriMapper&time=" + time.ToLongTimeString(), UriKind.Relative);

As you can see, the code is mostly the same, the difference is whether it is an explicit cancel-then-navigate or whether it is a simple URL-rewrite that happens. If you don’t know which one to use, I would recommend theUriMapper solution first (because you can easily extend it for other, non-dynamically-re-mapped scenarios) but it does require that you know what the final URI should be in a synchronous fashion. If for whatever reason you need to perform an asynchronous operation to determine which page to load – or if you just prefer a 100% code solution – you can use the “cancel navigation” approach. Just be sure to navigate within 10 seconds (or include a splash screen) or the system will terminate you for being unresponsive.

The attached sample lets you pick which approach you want to try by modifying the staticUSE_CANCEL_NAVIGATION flag set at the top of App.xaml.cs.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值