Restoring Pivot Scroll on WP7 Tombstone resume
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
- static ScrollViewer FindScrollViewer(DependencyObject parent)
- {
- var childCount = VisualTreeHelper.GetChildrenCount(parent);
- for (var i = 0; i < childCount; i++)
- {
- var elt = VisualTreeHelper.GetChild(parent, i);
- if (elt is ScrollViewer) return (ScrollViewer)elt;
- var result = FindScrollViewer(elt);
- if (result != null) return result;
- }
- return null;
- }
- protected override void
- OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
- {
- base.OnNavigatedFrom(e);
- State["MainPivot.SelectedIndex"] = MainPivot.SelectedIndex;
- var pivot = (PivotItem)MainPivot.SelectedItem;
- var scrollViewer = FindScrollViewer(pivot);
- State["scrollViewer.VerticalOffset"] = scrollViewer.VerticalOffset;
- _newPageInstance = false;
- State["PreservingPageState"] = true;
- }
- // Communicates scroll position between OnNavigatedTo and PivotLoaded
- private double _pivotScroll;
- protected override void
- OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
- {
- base.OnNavigatedTo(e);
- if (!_newPageInstance || !State.ContainsKey("PreservingPageState"))
- {
- return;
- }
- MainPivot.SelectedIndex = (int)State["MainPivot.SelectedIndex"];
- // Can&'t scroll now because Pivot&'s contents won&'t have been loaded
- _pivotScroll = (double)State["scrollViewer.VerticalOffset"];
- }
- // Hooked up to each pivot item&'s Loaded event handler.
- private void PivotLoaded(object sender, RoutedEventArgs e)
- {
- if (_pivotScroll == 0 || sender != MainPivot.SelectedItem) return;
- var pivot = (PivotItem)sender;
- var scrollViewer = FindScrollViewer(pivot);
- scrollViewer.ScrollToVerticalOffset(_pivotScroll);
- _pivotScroll = 0;
- }