I have an app and it works as expected on Windows 10. But on Windows 10 Mobile, when user presses back button, application closes. In my back requested event handler I even commented out GoBack() method but app still closes.
private void MobileNavigationService_BackRequested(object sender, BackRequestedEventArgs e)
{
e.Handled = true;
var navigationService = UnityConfiguration.Resolve<IMobileNavigationService>();
if (navigationService.CanGoBack())
{
//navigationService.GoBack();
}
}
I have a feeling that even though I set e.Handled = true it ignores it and acts like there is no handler.
Updated
As an additional information
App has only one page, Shell. it has common things like menu and title bar. It also has frame. In frame I open all the other pages. So going back, for my app, means going back in that frame, not in entire application. I want to override default behavior.
Setting up an event handler for BackRequested and to navigate back in the page stack.
Enabling and disabling the title bar back button based on the app's internal page stack.
You can get this DEMO from Microsoft in GitHub
Back Button Sample
protected override void OnNavigatedTo(NavigationEventArgs e)
{
bool optedIn = false;
if ((bool)e.Parameter)
{
optedIn = true;
}
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame.CanGoBack && optedIn)
{
// If we have pages in our in-app backstack and have opted in to showing back, do so
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
}
else
{
// Remove the UI from the title bar if there are no pages in our in-app back stack
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Collapsed;
}
}
Related
I want to ask the user whether they are sure that they wanna move back or not and only move back if they select "Yes", for that I am using a message dialog, but the problem is when I press the back button it moves back and after that the dialog pops up asking whether I want to move back or not.
I checked with break point as soon as messageDialog.ShowAsync executes the page moves back.
Code
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
SystemNavigationManager.GetForCurrentView().BackRequested += SampleConditionalNavigation_BackRequested;
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Collapsed;
SystemNavigationManager.GetForCurrentView().BackRequested -= SampleConditionalNavigation_BackRequested;
}
private async void SampleConditionalNavigation_BackRequested(object sender, BackRequestedEventArgs e)
{
e.Handled = true; // I have also tried setting it to false
var messageDialog = new MessageDialog("Are you sure you want to move back?") { Title = "Confirmation" };
// Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers
messageDialog.Commands.Add(new UICommand("Yes"));
messageDialog.Commands.Add(new UICommand("No"));
// Set the command that will be invoked by default
messageDialog.DefaultCommandIndex = 0;
// Set the command to be invoked when escape is pressed
messageDialog.CancelCommandIndex = 1;
//ShowDialog
var result = await messageDialog.ShowAsync();
if (result.Label == "Yes")
{
var rootFrame = Window.Current.Content as Frame;
if (rootFrame?.CanGoBack is true)
{
rootFrame?.GoBack();
}
}
}
Update 1
even if I comment the code where dialog shows itself the page still navigates back, it seems that e.Handled = true is pretty much useless here
This code is absolutely correct and works perfectly, the issue was that my app had BackRequested event in app.xaml.cs as well and that event was executing and navigating back before this method on this page was able to execute. Removing it from app.xaml.cs fixed the issue.
I've been trying to intercept the user going back from a page in my Xamarin.Forms UWP app, in order to either block it or present them with an "Are you sure?" dialog.
I've been able to remove the navigation bar back button using this in the constructor of the ContentPage:
NavigationPage.SetHasBackButton(this, false);
However, the back button on the mouse (XButton1) still causes the page to back.
I tried disabling it using this on the page:
protected override bool OnBackButtonPressed()
{
return true;
}
This would disable the hardware back button on something like Android, but it is not called at all when hitting the mouse back button.
I've also tried playing with the PointerPressed event on the UWP MainPage:
public MainPage()
{
this.InitializeComponent();
LoadApplication(new MyApp.App());
this.PointerPressed += MainPage_PointerPressed;
}
private void MainPage_PointerPressed(object sender, PointerRoutedEventArgs e)
{
PointerPoint currentPoint = e.GetCurrentPoint(this);
if (currentPoint.PointerDevice.PointerDeviceType == PointerDeviceType.Mouse)
{
PointerPointProperties pointerProperties = currentPoint.Properties;
if (pointerProperties.IsXButton1Pressed)
{
// back button pressed
}
}
}
This method is called correctly for all mouse inputs except for the XButton1 mouse back button if the app's current page is currently in a NavigationPage - almost like Xamarin.Forms is intercepting it somewhere along the way. Outside of a navigation page it picks up the XButton1 fine, and it always picks up every other input (including XButton2).
Is there a way to intercept or disable the XButton1 back function for a Xamarin.Forms UWP app?
Found a renderer workaround that allows you to handle the back button:
using Xamarin.Forms.Platform.UWP;
using Windows.UI.Xaml.Input;
using Windows.Devices.Input;
[assembly: ExportRenderer(typeof(Xamarin.Forms.Page), typeof(MyApp.UWP.Renderers.PageCustomRenderer))]
namespace MyApp.UWP.Renderers
{
public class PageCustomRenderer : PageRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Page> e)
{
base.OnElementChanged(e);
this.PointerPressed += PageCustomRenderer_PointerPressed;
}
private void PageCustomRenderer_PointerPressed(object sender, PointerRoutedEventArgs e)
{
if (e.Handled) return;
var point = e.GetCurrentPoint(Control);
if (point == null || point.PointerDevice.PointerDeviceType != PointerDeviceType.Mouse) return;
if (point.Properties.IsXButton1Pressed)
{
e.Handled = true;
if (Element != null)
{
Element.SendBackButtonPressed();
}
}
}
}
}
You can then override OnBackButtonPressed on the page as in the OP to stop it (or remove the Element.SendBackButtonPressed() from the renderer above to disable it entirely).
Is there a way i can "suspend" a UWP app by pressing the back button.
I'm not even sure suspending is the right term but what i want to do is to close the app when the user presses the back button rather than going back to the Signup/Login page in my app.
I want the app go close but also still be shown when the user opens the recent apps menu by holding the back button.
Heres my code in the App.Xaml.Cs
private void OnBackRequested(object sender, Windows.UI.Core.BackRequestedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame.CurrentSourcePageType == typeof(Pages.Home))
{
App.Current.Exit();
}
if (rootFrame.CanGoBack)
{
e.Handled = true;
rootFrame.GoBack();
}
}
The Problem is with the App.Current.Exit();
it terminates the app where what i want to do is just close and and not go back to the MainPage.
How can I do that?
To leave your app without terminating it, just remove the App.Current.Exit(); and ignore the back event (e.Handled = false;). You will then get the default behavior which is to leave the app on mobile devices. On desktop, your app will stay on the page it is. You will then have to do anything that fit your need to save/restore your app in its appropriate state using the suspending/resuming event handlers.
void OnBackRequested(object sender, Windows.UI.Core.BackRequestedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame.CurrentSourcePageType == typeof(Pages.Home))
{
// ignore the event. We want the default system behavior
e.Handled = false;
}
else if (rootFrame.CanGoBack)
{
e.Handled = true;
rootFrame.GoBack();
}
}
I want to check if the current page that the user is on/viewing is a specific page - MainPage. If the user is on MainPage, I want to ensure pressing the back button does not navigate to the previous page but exit the application instead. Is there anyway to check what is the page the user is on currently?
Or is there any better way to achieve what I want to achieve: to ensure pressing the back button on MainPage does not navigate to previous page but exit the application instead?
Have a look at NavigationEventArgs.SourcePageType in the navigation methods. It will return the type of the current page.
NOTE
Until there is entry in the backstack the back button will navigate to that entry (page). If the backstack is empty pressing backbutton will close the app. In my apps when the users presses the home button (navigating to mainpage), I always remove everything from the backstack except for the MainPage, and this ensures that pressing back button on MainPage will always exit.
EDIT
Code that I use to go back to MainPage (The pro for this solution is that this way the navigation events of the pages in the backstack won't be called, because they are removed. If they weren't removed their navigation events would be called while traversing through the backstack, which could cause unexpected behavior.):
private void goHome() {
var bs = Frame.BackStack.Where(b => b.SourcePageType.Name == "MainPage").FirstOrDefault();
if (bs != null)
{
Frame.BackStack.Clear();
Frame.BackStack.Add(bs);
}
this.Frame.GoBack();
}
You can use this code for that:
Put this in App.xaml.cs at end of OnLaunched method,
// Register a handler for BackRequested events and set the
// visibility of the Back button
SystemNavigationManager.GetForCurrentView().BackRequested += OnBackRequested;
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
rootFrame.CanGoBack ?
AppViewBackButtonVisibility.Visible :
AppViewBackButtonVisibility.Collapsed;
And write this method,
private void OnBackRequested(object sender, BackRequestedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame.CanGoBack)
{
e.Handled = true;
rootFrame.GoBack();
}
//you can check for this here rootFrame.BackStack[rootFrame.BackStack.Count-1].SourcePageType.Name
}
Also you can check for pages and control the visibility of back button in Desktop apps like this,
private void OnNavigated(object sender, NavigationEventArgs e)
{
// Each time a navigation event occurs, update the Back button's visibility
Frame rootFrame = (Frame)sender;
if (rootFrame.BackStack != null && rootFrame.BackStack.Count == 1)
{
// take care in page names
if (rootFrame.BackStack[0].SourcePageType.Name == "MainPage"
|| rootFrame.BackStack[0].SourcePageType.Name == "AnyOtherPage")
{
rootFrame.BackStack.RemoveAt(0);
}
}
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
((Frame)sender).CanGoBack ?
AppViewBackButtonVisibility.Visible :
AppViewBackButtonVisibility.Collapsed;
}
I made a WebBrowser and it works except the back button after pressing the back button the app closes and does not go back one in history. How can I solve the problem? I found solutions in the internet but they don't seem to work.
public MainPage()
{
this.InitializeComponent();
this.webBrowser.Navigate(new Uri("http://www.google.com", UriKind.Absolute));
this.webBrowser.LoadCompleted += webBrowser_LoadCompleted;
this.webBrowser.NavigationFailed += webBrowser_NavigationFailed;
this.webBrowser.IsScriptEnabled = true;
}
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
webBrowser.InvokeScript("eval", "history.go(-1)" );
}
P. S.:that is not the whole script but i think the rest is unneccesary if not tell me :)
P. P. S.:I'm new to Windows Phone programing.
Web browser is just a control inside the page and pressing the device back button navigates back to the previous page or exits the app if it has only one page. So, you would need to stop page navigation on back key press something like this.
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
e.Cancel=true;
}
This prevents a backnavigation
Now rest is to go to the previous page which can be done by
webBrowser.InvokeScript("eval", "history.go(-1)" );
so the event becomes
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
e.Cancel=true;
webBrowser.InvokeScript("eval", "history.go(-1)" );
}
Try to do:
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
WB1.InvokeScript("eval", "history.go(-1)");
e.Cancel = true;
}
When you override OnBackKeyPress, and you don't perform e.Cancel = true; it will do your code, but will also do what normal BackButton does - NavigateBack, Exit App and so on. But you must remember to leave the User an ability to exit your App or Navigate Back, so it will be more suitable to check some conditions (e.g. your webbrowser history is not null) and then do e.Canel, otherwise Exit the App.
To exit the app when you are in the root (so you can approve the cerfitication requirements), and also go back in navigation until you are in the root, try with this
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
if (MiniBrowser.CanGoBack){
e.Cancel = true;
MiniBrowser.InvokeScript("eval", "history.go(-1)");
}
}