EvenTiles from Start to Finish–Part 8

In the previous episode of this series about how to develop a Windows Phone application from scratch we talked about Fast Application Switching and Tombstoning. We saw how Visual Studio 2010 can help us testing Tombstoning scenarios. We also covered how to preserve application data when the application is interrupted by other applications and how to restore that data when returning to the foreground.

Right now we will extend our knowledge about Fast Application Switching and Tombstoning by trying to exactly restore a page after the application returns from the background. For that, we will take a look at the following scenario.

imageThe user is entering data in the textbox inside the SettingsPage. This means that a keyboard is visible and that the textbox has input focus and a blinking cursor at the location where data is entered. Sometime in the middle of entering text, the user hits the start button to activate another application, to return to our application only after a while. Even though we have stored all data the user entered (because we are saving the contents of the textbox when navigating away from the SettingsPage), the text box does not have focus when the user returns to the SettingsPage, nor a cursor positioned at the right location. In order to restore the exact same situation, we need to store additional data when navigating away from the SettingsPage. This leads to another challenge. To store the local page state when we are navigating away from the SettingsPage we can use the following code:

Saving the Page State
  1. protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
  2. {
  3.     if (!e.IsNavigationInitiator)
  4.     {
  5.         TextBox tb = FocusManager.GetFocusedElement() as TextBox;
  6.  
  7.         if (tb != null)
  8.         {
  9.             this.State[keySelectionLength] = tb.SelectionLength;
  10.             this.State[keySelectionStart] = tb.SelectionStart;
  11.         }
  12.     }
  13.     App.ActualSecBackContent = tbBackContent.Text;
  14.     base.OnNavigatedFrom(e);
  15. }

Each time OnNavigatedFrom is called, there is a possibility that the application is moved to the background. If so, the property IsNavigationInitiator is false. If the application is moved to the background, we check if the textbox currently has focus. If so, we will store the location of the cursor by adding entries for both the SelectionStart (location where the cursor is) and SelectionLength. If on the other hand the textbox does not have focus, we don’t have to store page state information, just the Text property of the textbox.

Retrieving page state information back can be done in the OnNavigatedTo method as follows:

Restore the Page State
  1. protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
  2. {
  3.     tbBackContent.Text = App.ActualSecBackContent;
  4.     btnRestore.Visibility = tbBackContent.Text.Equals(App.DefaultSecBackContent) ?
  5.         System.Windows.Visibility.Collapsed : System.Windows.Visibility.Visible;
  6.  
  7.     if (this.State.ContainsKey(keySelectionLength))
  8.     {
  9.         tbBackContent.SelectionLength = (int)this.State[keySelectionLength];
  10.         tbBackContent.SelectionStart = (int)this.State[keySelectionStart];
  11.         focusToTextBox = true;
  12.     }
  13.     base.OnNavigatedTo(e);
  14. }

However, it is not possible to get the focus back to the textbox control in the OnNavigatedTo method, because the different UI elements are not yet initialized when OnNavigatedTo is called. That is the reason to set a boolean variable to true and actually give the textbox focus when the Loaded event on the page is fired. If the application is returning from the background and focusToTextBox is set to true, the tbBackContent textbox will get focus:

Restore textbox input focus
  1. private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
  2. {
  3.     if (focusToTextBox)
  4.     {
  5.         tbBackContent.Focus();
  6.     }
  7. }

If an application would always be tombstoned, this would be sufficient to store / restore state information for the page and to restore the input focus if the textbox had focus when the application was put in the background. However, with Windows Phone Mango, applications can benefit from the Dormant state, where they stay in memory even though being in the background. There is not really a clear distinction from a developer’s point of view between Dormant and Tombstoned, except for the fact that in case of returning from being Tombstoned, the page constructor is executed, something that is not the case when the application returns from Dormant since the application was still in memory. As a consequence, returning from the Dormant state also means that the Loaded event on the page is not fired. So, even though returning to the foreground is faster if we were in the Dormant state, we need some additional logic to give the textbox focus in this case. In order to distinguish between Dormant and Tombstoned, it is possible to set a boolean variable in the constructor of a page to true and check that variable in the OnNavigatedTo method:

Dormant vs Tombstoned
  1. private bool focusToTextBox;
  2. private bool pageConstructed;
  3.  
  4. public SettingsPage()
  5. {
  6.     InitializeComponent();
  7.     pageConstructed = true;
  8. }

The value of the pageConstructed variable determines if we are returning from a Dormant state to the foreground (false) or not. If we are not returning from a Dormant state, we need to determine in OnNavigatedTo if we returned from a Tombstoned state in order to optionally set the focus to the textbox. However, if we are returning from a Dormant situation, the OnNavigatedTo method itself must be used to set focus to the textbox if needed. The modified OnNavigatedTo method looks like this:

Complete Page Reconstruction
  1. protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
  2. {
  3.     tbBackContent.Text = App.ActualSecBackContent;
  4.     btnRestore.Visibility = tbBackContent.Text.Equals(App.DefaultSecBackContent) ?
  5.         System.Windows.Visibility.Collapsed : System.Windows.Visibility.Visible;
  6.  
  7.     if (this.State.ContainsKey(keySelectionLength))
  8.     {
  9.         tbBackContent.SelectionLength = (int)this.State[keySelectionLength];
  10.         tbBackContent.SelectionStart = (int)this.State[keySelectionStart];
  11.         if (!pageConstructed)
  12.         {
  13.             tbBackContent.Focus();
  14.         }
  15.         else
  16.         {
  17.             focusToTextBox = true;
  18.         }
  19.     }
  20.     base.OnNavigatedTo(e);
  21. }

The following video shows how to save and restore the page state for the SettingsPage of EvenTiles for the different application execution states:

Saving Page State and restoring Textbox Focus

Update after video creation: Even though it seems in the video that the application is working properly both when returning from Dormant and from Tombstoning states, this is not entirely the case. Even though the focus of the Textbox is restored properly when needed, the Textbox will also get focus each and every time we return from the background, with the exception of the first time. The reason for that is that the dictionary entries in the Page.State collection were not deleted after usages in the OnNavigatedTo method. The source code for EvenTiles contains a fix for this undocumented application feature.

If you want to take a look at the source code that we have available for EvenTiles so far, you can download the entire solution belonging to this episode:

Download EvenTiles Episode 8 Source Code

After downloading and unzipping the sample code, you can open the EvenTiles solution in Visual Studio 2010 Express for Windows Phone. You must have the Windows Phone SDK 7.1 installed on your development system to do so. If you have a developer unlocked phone you can deploy the application to your phone, if you don’t have a developer unlocked phone you can still experiment with this application inside the emulator.

In the next episode of EvenTiles we will finally get to the heart and soul of the application, when we are going to create a Secondary Tile.

One thought on “EvenTiles from Start to Finish–Part 8

Comments are closed.