Skip to content

Commit

Permalink
Readd navigation stack capabilities (#1384)
Browse files Browse the repository at this point in the history
<!--- Provide a general summary of your changes in the Title above -->

## Description
<!--- Describe your changes in detail -->
Adding back the usage of the NavigationHelper to allow navigating
between pages. Note that certain APIs are missing in WinUI 3 compared to
UWP so we are diverging from the WinUI 2 version here.

## Motivation and Context
<!--- Why is this change required? What problem does it solve? -->
<!--- If it fixes an open issue, please link to the issue here. -->
Fixes #1205 

## Types of changes
<!--- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
  • Loading branch information
marcelwgn authored and karkarl committed Jul 15, 2024
1 parent fc4e06b commit 0488617
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 16 deletions.
90 changes: 74 additions & 16 deletions WinUIGallery/Helper/NavigationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
using AppUIBasics.Common;

using Windows.UI.Core;
using Microsoft.UI.Input;

namespace AppUIBasics.Helper
{
Expand Down Expand Up @@ -168,14 +169,15 @@ public void OnNavigatedFrom(NavigationEventArgs e)
public class RootFrameNavigationHelper
{
private Frame Frame { get; set; }
private Microsoft.UI.Xaml.Controls.NavigationView CurrentNavView { get; set; }
private NavigationView CurrentNavView { get; set; }
private bool isKeyDownProcessed = false;

/// <summary>
/// Initializes a new instance of the <see cref="RootNavigationHelper"/> class.
/// </summary>
/// <param name="rootFrame">A reference to the top-level frame.
/// This reference allows for frame manipulation and to register navigation handlers.</param>
public RootFrameNavigationHelper(Frame rootFrame, Microsoft.UI.Xaml.Controls.NavigationView currentNavView)
public RootFrameNavigationHelper(Frame rootFrame, NavigationView currentNavView)
{
this.Frame = rootFrame;
this.Frame.Navigated += (s, e) =>
Expand All @@ -185,27 +187,25 @@ public RootFrameNavigationHelper(Frame rootFrame, Microsoft.UI.Xaml.Controls.Nav
};
this.CurrentNavView = currentNavView;

// must register back requested on navview
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 6))
{
CurrentNavView.BackRequested += NavView_BackRequested;
}
CurrentNavView.BackRequested += NavView_BackRequested;
CurrentNavView.KeyDown += CurrentNavView_KeyDown;
CurrentNavView.KeyUp += CurrentNavView_KeyUp;
}

private void NavView_BackRequested(Microsoft.UI.Xaml.Controls.NavigationView sender, Microsoft.UI.Xaml.Controls.NavigationViewBackRequestedEventArgs args)
private void NavView_BackRequested(NavigationView sender, NavigationViewBackRequestedEventArgs args)
{
TryGoBack();
}

private bool TryGoBack()
{
// don't go back if the nav pane is overlayed
if (this.CurrentNavView.IsPaneOpen && (this.CurrentNavView.DisplayMode == Microsoft.UI.Xaml.Controls.NavigationViewDisplayMode.Compact || this.CurrentNavView.DisplayMode == Microsoft.UI.Xaml.Controls.NavigationViewDisplayMode.Minimal))
bool navigated = false;
// Don't go back if the nav pane is overlayed.
if (this.CurrentNavView.IsPaneOpen && (this.CurrentNavView.DisplayMode == NavigationViewDisplayMode.Compact || this.CurrentNavView.DisplayMode == NavigationViewDisplayMode.Minimal))
{
return false;
return navigated;
}

bool navigated = false;
if (this.Frame.CanGoBack)
{
this.Frame.GoBack();
Expand All @@ -215,13 +215,71 @@ private bool TryGoBack()
return navigated;
}

private bool TryGoForward()
{
bool navigated = false;
if (this.Frame.CanGoForward)
{
this.Frame.GoForward();
navigated = true;
}
return navigated;
}

private void UpdateBackButton()
{
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 6))
this.CurrentNavView.IsBackEnabled = this.Frame.CanGoBack ? true : false;
}

/// <summary>
/// Invoked on every keystroke, including system keys such as Alt key combinations.
/// Used to detect keyboard navigation between pages even when the page itself
/// doesn't have focus.
/// </summary>
/// <param name="sender">Instance that triggered the event.</param>
/// <param name="e">Event data describing the conditions that led to the event.</param>

private void CurrentNavView_KeyDown(object sender, Microsoft.UI.Xaml.Input.KeyRoutedEventArgs e)
{
if (e.Handled || isKeyDownProcessed)
{
// this.CurrentNavView.IsBackButtonVisible = this.Frame.CanGoBack ? NavigationViewBackButtonVisible.Visible : NavigationViewBackButtonVisible.Collapsed;
this.CurrentNavView.IsBackEnabled = this.Frame.CanGoBack ? true : false;
return;
}

var virtualKey = e.Key;

// Only investigate further when Left, Right, or the dedicated
// Previous or Next keys are pressed.
if (virtualKey == VirtualKey.Left || virtualKey == VirtualKey.Right ||
(int)virtualKey == 166 || (int)virtualKey == 167)
{
var downState = CoreVirtualKeyStates.Down;
// VirtualKeys 'Menu' key is also the 'Alt' key on the keyboard.
bool isMenuKeyPressed = (InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Menu) & downState) == downState;
bool isControlKeyPressed = (InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Control) & downState) == downState;
bool isShiftKeyPressed = (InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Shift) & downState) == downState;
bool isModifierKeyPressed = !isMenuKeyPressed && !isControlKeyPressed && !isShiftKeyPressed;
bool isOnlyAltPressed = isMenuKeyPressed && !isControlKeyPressed && !isShiftKeyPressed;

if (((int)virtualKey == 166 && isModifierKeyPressed) ||
(virtualKey == VirtualKey.Left && isOnlyAltPressed))
{
// When the previous key or Alt+Left are pressed navigate back.
e.Handled = TryGoBack();
}
else if (((int)virtualKey == 167 && isModifierKeyPressed) ||
(virtualKey == VirtualKey.Right && isOnlyAltPressed))
{
// When the next key or Alt+Right are pressed navigate forward.
e.Handled = TryGoForward();
}
isKeyDownProcessed = e.Handled;
}
}

private void CurrentNavView_KeyUp(object sender, Microsoft.UI.Xaml.Input.KeyRoutedEventArgs e)
{
isKeyDownProcessed = false;
}
}

Expand Down
3 changes: 3 additions & 0 deletions WinUIGallery/Navigation/NavigationRootPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public sealed partial class NavigationRootPage : Page
{
public Windows.System.VirtualKey ArrowKey;
public Microsoft.UI.Dispatching.DispatcherQueue dispatcherQueue;
private RootFrameNavigationHelper _navHelper;
private UISettings _settings;


Expand Down Expand Up @@ -74,6 +75,8 @@ public NavigationRootPage()
this.InitializeComponent();
dispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread();

_navHelper = new RootFrameNavigationHelper(rootFrame, NavigationViewControl);

SetDeviceFamily();
AddNavigationMenuItems();

Expand Down

0 comments on commit 0488617

Please sign in to comment.