1

I am using prism for my windows phone 8.1 runtime app, i want few conditions to be written in my code on backbutton press, so even though prism will take care of hardware backbutton flow i need to handle it in my local page(either inside cs page or view model), so i override the OnHardwareButtonsBackPressed method in my app.cs page and in my local page i will register and unregister hardware backbutton event in onnavigatedto and onnavigatedfrom method respectively and write my logic, it works fine for me until the app goes background, once if my app goes background and comes back the registered hardware backbutton event is unregistered automatically and from then the back flow is not working.

//App.cs 

    public sealed partial class App : MvvmAppBase
        {
            public App()
            {
                this.InitializeComponent();
            }

            protected override Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args)
            {
                NavigationService.Navigate("Main", null);
                return Task.FromResult<object>(null);
            }

    #if WINDOWS_PHONE_APP
            protected async override void OnHardwareButtonsBackPressed(object sender, Windows.Phone.UI.Input.BackPressedEventArgs e)
            {
                var currentFrame = Window.Current.Content as Frame;
                var currentView = currentFrame.Content as IView;

                if (currentView != null)
                {
                    var backNavigationVM = currentView.DataContext as IBackNavigation;

                    if ((backNavigationVM == null || backNavigationVM.CanGoBack))
                    {
                        base.OnHardwareButtonsBackPressed(sender, e);
                    }
                    else
                    {
                        e.Handled = true;
                    }
                }
                else
                {
                    e.Handled = true;
                }
            }

    #endif


        }


//My page.xaml

    <storeApps:VisualStateAwarePage
        x:Class="BackButtonWithPrism.Views.SecondPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:BackButtonWithPrism.Views"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
        xmlns:storeApps="using:Microsoft.Practices.Prism.StoreApps"
        xmlns:mvvm="using:Microsoft.Practices.Prism.Mvvm"                                
        mvvm:ViewModelLocator.AutoWireViewModel="True">

        <Grid>
            <TextBlock Text="SecondPage" FontSize="{StaticResource TextStyleLargeFontSize}" HorizontalAlignment="Center"></TextBlock>
            <Grid x:Name="FirstGrid">
                <Button HorizontalAlignment="Center" Content="FirstGrid" Click="Button_Click"></Button>
            </Grid>
            <Grid x:Name="SecondGrid">
                <Button HorizontalAlignment="Center" x:Name="btnSecond" Content="SecondGrid"></Button>
            </Grid>
        </Grid>
    </storeApps:VisualStateAwarePage>


//My page.cs

 public sealed partial class SecondPage : VisualStateAwarePage
    {
        public SecondPage()
        {
            this.InitializeComponent();
            this.NavigationCacheMode = NavigationCacheMode.Required;
        }

        protected async override void OnNavigatedTo(NavigationEventArgs e)
        {
            FirstGrid.Visibility = Visibility.Visible;
            SecondGrid.Visibility = Visibility.Collapsed;

#if WINDOWS_PHONE_APP
            Windows.Phone.UI.Input.HardwareButtons.BackPressed += HardwareButtons_BackPressed;

#endif
        }


#if WINDOWS_PHONE_APP
        private async void HardwareButtons_BackPressed(object sender, Windows.Phone.UI.Input.BackPressedEventArgs e)
        {

            if (FirstGrid.Visibility == Visibility.Collapsed)
            {
                e.Handled = true;
                FirstGrid.Visibility = Visibility.Visible;
                SecondGrid.Visibility = Visibility.Collapsed;
            }
            else
            {
                Frame currentFrame = Window.Current.Content as Frame;
                if (currentFrame == null)
                {
                    return;
                }
                else if (currentFrame.CanGoBack)
                {
                    currentFrame.GoBack();
                    e.Handled = true;
                }
            }
        }
#endif

        protected async override void OnNavigatedFrom(NavigationEventArgs e)
        {

            Windows.Phone.UI.Input.HardwareButtons.BackPressed -= HardwareButtons_BackPressed;

        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            FirstGrid.Visibility = Visibility.Collapsed;
            SecondGrid.Visibility = Visibility.Visible;
        }


    }


//My Page ViewModel:


public class SecondPageViewModel : ViewModel, IBackNavigation
{
    public bool CanGoBack
    {
        get;
        set;
    }
}

here all my logic i have written in my cs page instead of writting in viewmodel but i ill do it later.

Nambukarthy
  • 96
  • 11

1 Answers1

0

Your problem is related to OnNavigatedFrom() implementation. This method is called, when the application is deactivated and goes to background, causing deregistration of back-button handler. Unfortunately the OnNavigatedTo() is not called to pair it, when application is activated. Instead another event should be handled - Window.Activated. If you don't want to complicate your code to much, just try to put wrap removal of back-button handler with following condition. Forward request with a type of a current page is passed, when app goes to background.

if (e.NavigationMode != NavigationMode.Forward || e.SourcePageType != GetType())
{
    HardwareButtons.BackPressed -= ...
}

One final hint. When you put a breakpoint inside the IDE and launch debugger application will never be suspended and will never receive respective events. To simulate them (i.e. activated, suspended, and terminated) check here or here.

Community
  • 1
  • 1
Pawel Hofman
  • 1,326
  • 11
  • 10