Windows Phone 8.1 override back button on a certain page

5.4k views Asked by At

I am developing a WP 8.1 XAML app. The first page is a login page, the second for example a history page. There will be more pages, but it doesn't matter at the moment. When I press the login button on the login page, the second (history) page appears. If I press the (physical) back button on the history page, it goes back to the login page. But I would like to disable this function. Instead of this I would like when I press the back button a MessageDialog appears and if I press again within a few seconds (for example 3 secs) the app terminates. I tried to find the answer for my questions, but it doesn't work properly. I tried this on the login page:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    HardwareButtons.BackPressed += HardwareButtons_BackPressed;
}
private void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
    if (Frame.CurrentSourcePageType.FullName == "MyAppName.History")
        Application.Current.Exit();
}

My app terminates when I press the back button on the second (history) page. But if I try to count the pressing of back button, it will navigate back to the login page. After this when I login again and press the back button the counter will be 2 and the app will exit. Here is the code what I tried:

private void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
    //MessageDialog msgbox = new MessageDialog("This is a popup message");
    //await msgbox.ShowAsync(); 
    //e.Handled = true;
    backPressCount++;

    if (backPressCount==2 && Frame.CurrentSourcePageType.FullName == "MyAppName.History")
        Application.Current.Exit();
}

If I uncomment the 2 MessageDialog lines, the message appears, but I will be navigated back to the login page. And I tried to uncomment the e.Handled = true; line, but it didn't help. I think I should disable the back button on history page or override it fully. Anybody has idea for my problem?

EDIT: I rethink the back button behavivor, because I don't want to use ticker to measure the time between 2 press. Instead of this I would like only a popup message with a question, for example "Do you really want to quit?" and 2 buttons (Yes and No). It is works with the following code:

private async void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
    e.Handled = true;
    MessageDialog dlg = new MessageDialog("Are you sure you want to quit you will loose all your work ?", "Warning");
    dlg.Commands.Add(new UICommand("Yes", new UICommandInvokedHandler(CommandHandler1)));
    dlg.Commands.Add(new UICommand("No", new UICommandInvokedHandler(CommandHandler1)));

    await dlg.ShowAsync();
}

private void CommandHandler1(IUICommand command)
{
    var label = command.Label;
    switch (label)
    {
         case "Yes":
         {
              Application.Current.Exit();
              break;
          }
         case "No":
         {
              break;
        }
    }
}

My problem is I am navigated to login page before I choose an answer on the popup. If I press Yes on it my app exits, and do nothing when I choose No. But I am on the login page at the moment. I tried to use dlg.Show() instead of dlg.ShowAsync() but it is missing. So I can use only async method, but in this case the page navigate to login in the background, because the NavigationHelper is called always, when I push the back button. What is the problem?

1

There are 1 answers

0
Rob Caplan - MSFT On BEST ANSWER

Consider hard if this is what you really want to do. A more user friendly flow would be to save the data and let the user back out of the app and return. Also consider what happens if the user exits in a different way such as the window or camera button.

That said, the code you list will work if that's the only navigation handling that you have (try it in the BlankPage template). I suspect that it's not the only and you're using something like the NavigationHelper from the fuller templates such as BasicPage. In that case the NavigationHelper's GoBackCommand is probably triggering and calling Frame.GoBack.

You can override this behaviour by setting your own RelayCommand on the NavigationHelper's GoBackCommand property:

RelayCommand _checkedGoBackCommand;
public BasicPage1()
{
    this.InitializeComponent();

    this.navigationHelper = new NavigationHelper(this);
    this.navigationHelper.LoadState += this.NavigationHelper_LoadState;
    this.navigationHelper.SaveState += this.NavigationHelper_SaveState;

    _checkedGoBackCommand = new RelayCommand(
                                    () => this.CheckGoBack(),
                                    () => this.CanCheckGoBack()
                                );

    navigationHelper.GoBackCommand = _checkedGoBackCommand;
}

private bool CanCheckGoBack()
{
    return true;
}

private async void CheckGoBack()
{
    Debug.WriteLine("CheckGoBack"); 
    MessageDialog dlg = new MessageDialog("Are you sure you want to quit you will loose all your work ?", "Warning");
    dlg.Commands.Add(new UICommand("Yes", new UICommandInvokedHandler(CommandHandler1)));
    dlg.Commands.Add(new UICommand("No", new UICommandInvokedHandler(CommandHandler1)));

    await dlg.ShowAsync();
}

private void CommandHandler1(IUICommand command)
{
    var label = command.Label;
    switch (label)
    {
        case "Yes":
            {
                Application.Current.Exit();
                break;
            }
        case "No":
            {
                break;
            }
    }
}