using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Input; using Windows.System; using Windows.UI.Core; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation; namespace Common { [Windows.Foundation.Metadata.WebHostHidden] public class NavigationHelper : DependencyObject { private Page Page { get; set; } private Frame Frame { get { return this.Page.Frame; } } public NavigationHelper(Page page) { this.Page = page; } #region Process lifetime management private String _pageKey; public event SaveStateEventHandler SaveState; public void OnNavigatedTo(NavigationEventArgs e) { var frameState = SuspensionManager.SessionStateForFrame(this.Frame); this._pageKey = "Page-" + this.Frame.BackStackDepth; if (e.NavigationMode == NavigationMode.New) { // Clear existing state for forward navigation when adding a new page to the // navigation stack var nextPageKey = this._pageKey; int nextPageIndex = this.Frame.BackStackDepth; while (frameState.Remove(nextPageKey)) { nextPageIndex++; nextPageKey = "Page-" + nextPageIndex; } // Pass the navigation parameter to the new page if (this.LoadState != null) { this.LoadState(this, new LoadStateEventArgs(e.Parameter, null)); } } else { if (this.LoadState != null) { this.LoadState(this, new LoadStateEventArgs(e.Parameter, (Dictionary<String, Object>)frameState[this._pageKey])); } } } public void OnNavigatedFrom(NavigationEventArgs e) { var frameState = SuspensionManager.SessionStateForFrame(this.Frame); var pageState = new Dictionary<String, Object>(); if (this.SaveState != null) { this.SaveState(this, new SaveStateEventArgs(pageState)); } frameState[_pageKey] = pageState; } #endregion } [Windows.Foundation.Metadata.WebHostHidden] public class RootFrameNavigationHelper { private Frame Frame { get; set; } SystemNavigationManager systemNavigationManager; public RootFrameNavigationHelper(Frame rootFrame) { this.Frame = rootFrame; // Handle keyboard and mouse navigation requests this.systemNavigationManager = SystemNavigationManager.GetForCurrentView(); systemNavigationManager.BackRequested += SystemNavigationManager_BackRequested; UpdateBackButton(); // Listen to the window directly so we will respond to hotkeys regardless // of which element has focus. Window.Current.CoreWindow.Dispatcher.AcceleratorKeyActivated += CoreDispatcher_AcceleratorKeyActivated; Window.Current.CoreWindow.PointerPressed += this.CoreWindow_PointerPressed; // Update the Back button whenever a navigation occurs. this.Frame.Navigated += (s, e) => UpdateBackButton(); } private bool TryGoBack() { bool navigated = false; if (this.Frame.CanGoBack) { this.Frame.GoBack(); navigated = true; } return navigated; } private bool TryGoForward() { bool navigated = false; if (this.Frame.CanGoForward) { this.Frame.GoForward(); navigated = true; } return navigated; } private void SystemNavigationManager_BackRequested(object sender, BackRequestedEventArgs e) { if (!e.Handled) { e.Handled = TryGoBack(); } } private void UpdateBackButton() { systemNavigationManager.AppViewBackButtonVisibility = this.Frame.CanGoBack ? AppViewBackButtonVisibility.Visible : AppViewBackButtonVisibility.Collapsed; } private void CoreDispatcher_AcceleratorKeyActivated(CoreDispatcher sender, AcceleratorKeyEventArgs e) { var virtualKey = e.VirtualKey; // Only investigate further when Left, Right, or the dedicated Previous or Next keys // are pressed if ((e.EventType == CoreAcceleratorKeyEventType.SystemKeyDown || e.EventType == CoreAcceleratorKeyEventType.KeyDown) && (virtualKey == VirtualKey.Left || virtualKey == VirtualKey.Right || (int)virtualKey == 166 || (int)virtualKey == 167)) { var coreWindow = Window.Current.CoreWindow; var downState = CoreVirtualKeyStates.Down; bool menuKey = (coreWindow.GetKeyState(VirtualKey.Menu) & downState) == downState; bool controlKey = (coreWindow.GetKeyState(VirtualKey.Control) & downState) == downState; bool shiftKey = (coreWindow.GetKeyState(VirtualKey.Shift) & downState) == downState; bool noModifiers = !menuKey && !controlKey && !shiftKey; bool onlyAlt = menuKey && !controlKey && !shiftKey; if (((int)virtualKey == 166 && noModifiers) || (virtualKey == VirtualKey.Left && onlyAlt)) { // When the previous key or Alt+Left are pressed navigate back e.Handled = TryGoBack(); } else if (((int)virtualKey == 167 && noModifiers) || (virtualKey == VirtualKey.Right && onlyAlt)) { // When the next key or Alt+Right are pressed navigate forward e.Handled = TryGoForward(); } } } private void CoreWindow_PointerPressed(CoreWindow sender, PointerEventArgs e) { var properties = e.CurrentPoint.Properties; // Ignore button chords with the left, right, and middle buttons if (properties.IsLeftButtonPressed || properties.IsRightButtonPressed || properties.IsMiddleButtonPressed) return; // If back or foward are pressed (but not both) navigate appropriately bool backPressed = properties.IsXButton1Pressed; bool forwardPressed = properties.IsXButton2Pressed; if (backPressed ^ forwardPressed) { e.Handled = true; if (backPressed) this.TryGoBack(); if (forwardPressed) this.TryGoForward(); } } } public delegate void LoadStateEventHandler(object sender, LoadStateEventArgs e); public delegate void SaveStateEventHandler(object sender, SaveStateEventArgs e); public class LoadStateEventArgs : EventArgs { public Object NavigationParameter { get; private set; } public Dictionary<string, Object> PageState { get; private set; } public LoadStateEventArgs(Object navigationParameter, Dictionary<string, Object> pageState) : base() { this.NavigationParameter = navigationParameter; this.PageState = pageState; } } public class SaveStateEventArgs : EventArgs { public Dictionary<string, Object> PageState { get; private set; } public SaveStateEventArgs(Dictionary<string, Object> pageState) : base() { this.PageState = pageState; } } }