Putting the user back to the correct pivot item when they return to a tombestoned application whose last visited page contained a Pivot is pretty easy, but ensuring that they are put back to the right scroll position if they’ve scrolled down a list isn’t quite as easy.

In the code below I have a method which returns the first ScrollViewer under an item.  This works well for me, but if your PivotItem’s contents contain ScrollViewers then you’ll need something more sophistacated.

In the OnNavigatedFrom I follow the standard pattern Microsoft recommends, and store away the scroll offset in the page state.

In the OnNavigatedTo I recuperate the scroll position, but cannot yet scroll because the PivotItem’s contents have not been loaded.  Instead I store the scroll position, and then when the pivot has been loaded I then scroll.  In my XAML I hook up each PivotItem’s Loaded event to invoke PivotItemLoaded

Code Snippet
  1. static ScrollViewer FindScrollViewer(DependencyObject parent)
  2. {
  3.     var childCount = VisualTreeHelper.GetChildrenCount(parent);
  4.     for (var i = 0; i < childCount; i++)
  5.     {
  6.         var elt = VisualTreeHelper.GetChild(parent, i);
  7.         if (elt is ScrollViewer) return (ScrollViewer)elt;
  8.         var result = FindScrollViewer(elt);
  9.         if (result != null) return result;
  10.     }
  11.     return null;
  12. }
  13.  
  14. protected override void
  15.     OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
  16. {
  17.     base.OnNavigatedFrom(e);
  18.  
  19.     State["MainPivot.SelectedIndex"] = MainPivot.SelectedIndex;
  20.     var pivot = (PivotItem)MainPivot.SelectedItem;
  21.     var scrollViewer = FindScrollViewer(pivot);
  22.     State["scrollViewer.VerticalOffset"] = scrollViewer.VerticalOffset;
  23.     _newPageInstance = false;
  24.     State["PreservingPageState"] = true;
  25. }
  26.  
  27. // Communicates scroll position between OnNavigatedTo and PivotLoaded
  28. private double _pivotScroll;
  29.  
  30. protected override void
  31.     OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
  32. {
  33.     base.OnNavigatedTo(e);
  34.  
  35.     if (!_newPageInstance || !State.ContainsKey("PreservingPageState"))
  36.     {
  37.         return;
  38.     }
  39.  
  40.     MainPivot.SelectedIndex = (int)State["MainPivot.SelectedIndex"];
  41.  
  42.     // Can&'t scroll now because Pivot&'s contents won&'t have been loaded
  43.     _pivotScroll = (double)State["scrollViewer.VerticalOffset"];
  44. }
  45.  
  46. // Hooked up to each pivot item&'s Loaded event handler.
  47. private void PivotLoaded(object sender, RoutedEventArgs e)
  48. {
  49.     if (_pivotScroll == 0 || sender != MainPivot.SelectedItem) return;
  50.  
  51.     var pivot = (PivotItem)sender;
  52.     var scrollViewer = FindScrollViewer(pivot);
  53.     scrollViewer.ScrollToVerticalOffset(_pivotScroll);
  54.     _pivotScroll = 0;
  55. }