handling backpress event in windows phone 8.1 - c#

I want to handled the backpress button in windows phone 8.1 app.I want whenever backpress is pressed navigate to previous page but when backpress is pressed at the second page(after the mainpage) i want the app to exit or asked to exit.
i am using this code to navigate
Windows.Phone.UI.Input.HardwareButtons.BackPressed += HardwareButtons_BackPressed;
}
public bool Handled { get; set; }
private void HardwareButtons_BackPressed(object sender, Windows.Phone.UI.Input.BackPressedEventArgs e)
{
Frame frame = Window.Current.Content as Frame;
if (frame == null)
{
return;
}
if (frame.CanGoBack)
{
frame.GoBack();
e.Handled = true;
}
}

Try the following code. It works for me.
private async void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
e.Handled = true;
var curpage = rootFrame.CurrentSourcePageType.FullName;
if(curpage=="your page name where you want to show dialog")
{
var msg = new MessageDialog("Sure to Exit?");
var okBtn = new UICommand("OK");
var cancelBtn = new UICommand("Cancel");
msg.Commands.Add(okBtn);
msg.Commands.Add(cancelBtn);
IUICommand result = await msg.ShowAsync();
if (result != null && result.Label == "OK")
{
Application.Current.Exit();
}
}
else
{
if (rootFrame.CanGoBack)
{
rootFrame.GoBack();
}
}
}

My understanding to your quesiton is everytime when user what to navigate back to the first page by pressing back button, you want to exit the app. If so, what we need to do is in the first page's OnNavigatedFrom event to check if the NavigationMode is Back. Try the following code:
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
if(e.NavigationMode == NavigationMode.Back)
{
App.Current.Exit();
}
}

If you want to delete the history of the first navigated page, you can remove it from BackStack, and the second page is considered as first one. Just put this on your mainpage:
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
Frame.BackStack.Remove(Frame.BackStack.First());
base.OnNavigatedFrom(e);
}

Related

How to make UWP AppWindow enter full screen mode?

I'm using AppWindow to create multiple windows for the app, and I want the user to be able to make the windows full screen, but ApplicationView.TryEnterFullScreenMode doesn't work, it returns false all the time when used in an AppWindow.
Sample code from Microsoft Docs:
private void ToggleFullScreenModeButton_Click(object sender, RoutedEventArgs e)
{
var view = ApplicationView.GetForCurrentView();
if (view.IsFullScreenMode)
{
view.ExitFullScreenMode();
}
else
{
view.TryEnterFullScreenMode(); // Returns false in an AppWindow
}
}
How do you make an AppWindow enter full screen mode?
For AppWindow you should use AppWindowPresenter.RequestPresentation and pass AppWindowPresentationKind.FullScreen as parameter.
The solution I came up with (based on this answer) handles exiting full screen mode using:
The original button.
The back to window button in the title bar.
The escape key.
XAML:
<Button x:Name="ToggleFullScreenButton" Text="Full screen mode" Click="ToggleFullScreenButton_Click" />
Code behind:
public AppWindow AppWindow { get; } // This should be set to the AppWindow instance.
private void ToggleFullScreenButton_Click(object sender, RoutedEventArgs e)
{
var configuration = AppWindow.Presenter.GetConfiguration();
if (FullScreenButton.Text == "Exit full screen mode" && _tryExitFullScreen())
{
// Nothing, _tryExitFullScreen() worked.
}
else if (AppWindow.Presenter.RequestPresentation(AppWindowPresentationKind.FullScreen))
{
FullScreenButton.Text = "Exit full screen mode";
_ = Task.Run(async () =>
{
await Task.Delay(500); // Delay a bit as AppWindow.Changed gets fired many times on entering full screen mode.
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
AppWindow.Changed += AppWindow_Changed;
this.KeyDown += Page_KeyDown;
});
});
}
}
private bool _tryExitFullScreen()
{
if (AppWindow.Presenter.RequestPresentation(AppWindowPresentationKind.Default))
{
FullScreenButton.Text = "Full screen mode";
AppWindow.Changed -= AppWindow_Changed;
this.KeyDown -= Page_KeyDown;
return true;
}
return false;
}
// handles the back-to-window button in the title bar
private void AppWindow_Changed(AppWindow sender, AppWindowChangedEventArgs args)
{
if (args.DidSizeChange) // DidSizeChange seems good enough for this
{
_tryExitFullScreen();
}
}
// To make the escape key exit full screen mode.
private void Page_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Escape)
{
_tryExitFullScreen();
}
}

Hardware back button on windows phone 10 is not functioning

I have a problem with the hardware back button on windows phone 10 that does not work when the default page is the page BackgroundMusic.
App.cs
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
#if DEBUG
if (System.Diagnostics.Debugger.IsAttached)
{
this.DebugSettings.EnableFrameRateCounter = true;
}
#endif
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
rootFrame.Navigated += RootFrame_Navigated;
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
// 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;
}
if (e.PrelaunchActivated == false)
{
if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
rootFrame.Navigate(typeof(BackgroundMusic), e.Arguments);
}
// Ensure the current window is active
Window.Current.Activate();
}
}
private void RootFrame_Navigated(object sender, NavigationEventArgs e)
{
// Each time a navigation event occurs, update the Back button's visibility
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
((Frame)sender).CanGoBack ?
AppViewBackButtonVisibility.Visible :
AppViewBackButtonVisibility.Collapsed;
}
private void OnBackRequested(object sender, BackRequestedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (App.DetectPlatform() == Platform.WindowsPhone)
{
HardwareButtons.BackPressed += new EventHandler<BackPressedEventArgs>((s, a) =>
{
if (rootFrame.CanGoBack)
{
rootFrame.GoBack();
a.Handled = true;
}
});
}
else if (App.DetectPlatform() == Platform.Windows)
{
if (rootFrame.CanGoBack)
{
e.Handled = true;
rootFrame.GoBack();
}
}
}
public static Platform DetectPlatform()
{
bool isHardwareButtonsAPIPresent = ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons");
if (isHardwareButtonsAPIPresent)
{
return Platform.WindowsPhone;
}
else
{
return Platform.Windows;
}
}
public static MediaElement GlobalMediaElement
{
get { return Current.Resources["MyPlayer"] as MediaElement; }
}
private void mediaended(object sender, RoutedEventArgs e)
{
var AppMediaElement = App.GlobalMediaElement;
AppMediaElement.Position = TimeSpan.Zero;
AppMediaElement.Play();
}
BackgroundMusic.cs
const string soundTrackToken = "soundtrack";
int flag = 1;
public BackgroundMusic()
{
this.InitializeComponent();
}
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
//navigationHelper.OnNavigatedTo(e);
mainFrame.Navigate(typeof(MainPage));
if (StorageApplicationPermissions.FutureAccessList.ContainsItem(soundTrackToken))
{
StorageFile audioFile = await StorageApplicationPermissions.FutureAccessList.GetFileAsync(soundTrackToken);
if (audioFile != null)
{
await StartAudio(audioFile);
}
}
}
How to handle it?
Note:
- When the default page is MainPage, the hardware back button to work. But when the default page is the BackgroundMusic page, hardware back button does not work
- BackgroundMusic page is a page for background music (there is also a play and stop button) on the application.
Can you try this:
Under
SystemNavigationManager.GetForCurrentView().BackRequested += OnBackRequested;
put
HardwareButtons.BackPressed += OnBackRequested:
then delete this inside OnBackRequested
HardwareButtons.BackPressed += new EventHandler<BackPressedEventArgs>((s, a) =>
{
The explanation is that you need to register the event handler upfront. In your current code, you only handles software back button. When it is clicked and knowing that it is Phone platform, then you register a new event handler. So, what I suggested you to do is register the handler the same as the software back button up front, so it handles the same behavior, and you don't need to add new event handler if it is a phone later on.
First of all, when on windows phone you handled hardware back button like this:
if (App.DetectPlatform() == Platform.WindowsPhone)
{
HardwareButtons.BackPressed += new EventHandler<BackPressedEventArgs>((s, a) =>
{
if (rootFrame.CanGoBack)
{
rootFrame.GoBack();
a.Handled = true;
}
});
}
This is not right, it is like to handle the back button twice, two items in the BackStack of the rootFrame will be removed when back button is pressed on mobile. You can change this code like this:
if (App.DetectPlatform() == Platform.WindowsPhone)
{
if (rootFrame.CanGoBack)
{
rootFrame.GoBack();
e.Handled = true;
}
}
Secondly, in the OnNavigatedTo event of your BackgroundMusic, I don't know what is your mainFrame, if this is the Frame inside the BackgroundMusic page, then it can be navigated to MainPage, the BackStack of rootFrame will have no items. And if this mainFrame is exactly the rootFrame, navigation will failed when it is on the OnNavigatedTo event, the items' count BackStack of rootFrame still remains to be 0.
So if you want to use rootFrame to navigate to MainPage when the default Page of rootFrame is BackgroundMusic, you can in the Loaded event navigate to MainPage for example like this:
private void BackgroundMusic_Loaded(object sender, RoutedEventArgs e)
{
var status = this.Frame.Navigate(typeof(MainPage));
}

(UWP) Using ESC Key to Close ModalDialog

I'm displaying ModalDialog using sample code Busy.xaml in Template10 :
public static void SetBusy(bool busy, string text = null)
{
WindowWrapper.Current().Dispatcher.Dispatch(() =>
{
var modal = Window.Current.Content as ModalDialog;
var view = modal.ModalContent as Busy;
if (view == null)
modal.ModalContent = view = new Busy();
modal.IsModal = view.IsBusy = busy;
view.BusyText = text;
modal.CanBackButtonDismiss = true;
});
}
I can close this dialog by using ALT+Left Arrow, but on most Desktop application pressing ESC key usually will also close popup or dialog.
I try to add code to handle KeyDown on Busy.xaml but this method never executed when I press ESC or any key.
private void UserControl_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == VirtualKey.Escape)
{
e.Handled = true;
SetBusy(false);
}
}
So, how to make this ModalDialog close when user press ESC key ?
You have to attach an event handler to the CharacterReceived event of the CoreWindow.
Modify the SetBusy method:
public static void SetBusy(bool busy, string text = null)
{
WindowWrapper.Current().Dispatcher.Dispatch(() =>
{
var modal = Window.Current.Content as ModalDialog;
var view = modal.ModalContent as Busy;
if (view == null)
modal.ModalContent = view = new Busy();
modal.IsModal = view.IsBusy = busy;
view.BusyText = text;
modal.CanBackButtonDismiss = true;
// Attach to key inputs event
var coreWindow = Window.Current.CoreWindow;
coreWindow.CharacterReceived += CoreWindow_CharacterReceived;
});
}
Where as the CoreWindow_CharacterReceived would look like this:
private static void CoreWindow_CharacterReceived(CoreWindow sender,
CharacterReceivedEventArgs args)
{
// KeyCode 27 = Escape key
if (args.KeyCode != 27) return;
// Detatch from key inputs event
var coreWindow = Window.Current.CoreWindow;
coreWindow.CharacterReceived -= CoreWindow_CharacterReceived;
// TODO: Go back, close window, confirm, etc.
}
While the modal is open just use something along this route:
private void Modal_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
this.Close();
}
}
Another way to address (e.KeyCode==Keys.Escape) is:
(e.KeyChar == (char)27)
or
e.KeyCode==(char)Keys.Escape
For this code to work, you need Form.KeyPreview = true;
For more information on what's above: https://msdn.microsoft.com/en-us/library/system.windows.forms.control.keydown.aspx
I believe that you need to append the CancelButton Property for this to work properly.
(Almost the same approach) I believe this should work nicely as well:
private void HandleEsc(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape)
Close();
}
This is for a console application:
if (Console.ReadKey().Key == ConsoleKey.Escape)
{
return;
}

Hardware Back button closes app

When I press on the hardware back button in my uwp app, the app closes. I use the hamburger interface from Template 10.
I added the following code in the app.xaml.cs and in het schell.xaml.cs but when I press back it says that the parameter canGoBack is false and closes the app.
public Shell(INavigationService navigationService)
{
Instance = this;
InitializeComponent();
// setup for static calls
Window = WindowWrapper.Current();
MyHamburgerMenu.NavigationService = navigationService;
// any nav change, reset to normal
navigationService.FrameFacade.Navigated += (s, e) =>
BusyModal.IsModal = LoginModal.IsModal = false;
SystemNavigationManager.GetForCurrentView().BackRequested += Shell_BackRequested;
}
private void Shell_BackRequested(object sender, BackRequestedEventArgs e)
{
MyHamburgerMenu.NavigationService.GoBack();
}
This is how you should handle the BackRequested event for a default implementation:
SystemNavigationManager.GetForCurrentView().BackRequested += (sender, e) =>
{
if (!e.Handled && Frame.CanGoBack)
{
e.Handled = true;
AppFrame.GoBack();
}
};
Remember that for CanGoBack to be true you should call first a Frame.Navigate()
If there are frames in the Frame.BackStack, then CanGoBack will be true.

Cancel opening link in browser

In my Windows phone application I use RichTextBox element
I have a hyperlink on it, and when user click on it there is a dialog: Do you want to open this link in exteranl browser. If user say no, external browser shouldn't be opened. I cancel navigation but in any case - external browser opens. How can I cancel opening link in browser?
//Constructor
static Helper()
{
var phoneApplicationFrame = Application.Current.RootVisual as PhoneApplicationFrame;
if (Application.Current.RootVisual as PhoneApplicationFrame != null)
{
phoneApplicationFrame.Navigating += new NavigatingCancelEventHandler(NavigationService_Navigating);
}
}
link.Foreground = new SolidColorBrush(Colors.Blue);
link.MouseOverForeground = new SolidColorBrush(Colors.Blue);
link.TargetName = "_blank";
var linkText = new Run() { Text = linkDesc };
link.Inlines.Add(linkText);
link.Click += new RoutedEventHandler(NavidateTo);
private static void NavidateTo(object sender, RoutedEventArgs routedEventArgs)
{
if (MessageBox.Show(
Constants.BrowserNavigating,
"",
MessageBoxButton.OKCancel) == MessageBoxResult.Cancel)
{
StateManager.Set("ExternalBrowser", "true");
}
else
{
StateManager.Set("Browser", "true");
}
}
public static void NavigationService_Navigating(object sender, NavigatingCancelEventArgs e)
{
var res = StateManager.Get("ExternalBrowser");
if (res != null)
{
StateManager.Remove("ExternalBrowser");
e.Cancel = true;
}
}
Rather than have the HyperlinkButton open the link itself, don't specify the NavigationUri but handle the Tap event yourself.
In the eventhandler ask the question and only open the browser if they say yes.
This will be much simpler than trying to cancel something that is already in progress.

Categories

Resources