Improving application stability by managing button states

While testing applications on Windows Phone we have often come across scenarios where application crashes when user clicks buttons or links in the app in quick succession. These type of crashes generally occur due to two main reasons

1) Controls for user inputs don’t get disabled once user taps on them and until a response has been processed. Example while the app is processing user’s selection choice from the list, it takes some time to process the request and user changes his mind and clicks on another item, or submit button for app is enabled even while the app is signing the user into the application on the first click of the button by the user, like below.

Button_Not_Disabled

  

To avoid such crashes, controls that require user action should not be available for the user to interact with again after a user initially interacts with them until a response is posted.

2) Click events are handled when app is being removed from the foreground but before the app completely transitions to deactivated state. This happens when a user interaction causes the app to navigate the user out of the app. An example of this would be when invoking the EmailComposeTask, SmsComposeTask or WebBrowserTask, for instance if the user taps the email link in the below page multiple times in quick succession then the app is likely to crash.

Email_Link

The crash log in this case would resemble something as below

System.InvalidOperationException: Navigation is not allowed when the task is not in the foreground. Error: -2147220990

   at Microsoft.Phone.Shell.Interop.ShellPageManagerNativeMethods.CheckHResult(Int32 hr)

   at Microsoft.Phone.Shell.Interop.ShellPageManager.NavigateToExternalPage(String pageUri, Byte[] args)

   at Microsoft.Phone.Tasks.ChooserHelper.Navigate(Uri appUri, ParameterPropertyBag ppb)

   at Microsoft.Phone.Tasks.EmailComposeTask.Show()

   at AppName.View.SharePage.mailHyperlinkButton_Click(Object sender, RoutedEventArgs e)

   at System.Windows.Controls.Primitives.ButtonBase.OnClick()

   at System.Windows.Controls.HyperlinkButton.OnClick()

   at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)

   at System.Windows.Controls.Control.OnMouseLeftButtonUp(Control ctrl, EventArgs e)

   at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, Int32 actualArgsTypeIndex, String eventName)

The happy path is that EmailComposeTask is invoked when user taps the email link, the email dialog opens and the application gets deactivated i.e. sent to the background. However in above case as the email link was tapped multiple times, the second click is being handled after the email dialog is being opened, but before the app moves to deactivated state. Solution is to put a try/catch around the EmailComposeTask and handle the InvalidOperationException.

EmailComposeTask emailComposeTask = new EmailComposeTask();
emailComposeTask.To = "test@test.com";
emailComposeTask.Subject = "Feedback for wpdps";
try
{
  emailComposeTask.Show();

}

catch(InvalidOperationException)
{
  // can fail if link is pressed twice in quick `` succession -   do nothing as the application `` has already navigated away ``}

The above solution also holds good for SmsComposeTask and WebBrowserTask.

Written by Amit Jain