Skip to content

Commit

Permalink
Merge pull request #1456 from unoplatform/dev/lubl/nav-pages
Browse files Browse the repository at this point in the history
docs(nav): Add page navigation to tutorial
  • Loading branch information
nickrandolph authored Jun 2, 2023
2 parents e39c283 + 7a86628 commit 8164adc
Show file tree
Hide file tree
Showing 6 changed files with 385 additions and 87 deletions.
Original file line number Diff line number Diff line change
@@ -1,20 +1,46 @@
---
uid: Learn.Tutorials.Navigation.Advanced.PageNavigation
---
# How-To: Advanced Page Navigation
# How-To: Employ Advanced Page Navigation Techniques

Sometimes when you navigate you don't want to leave the current page in the back-stack. For example after signing into an application, you might want to navigate to the main page of the application; you don't want to have the login page still in the back-stack for a user to accidentally to go back to.
When using navigation, you may not want to allow the current page to remain in the back-stack. If you want to navigate to the main page of the application after signing in, there should not be a login page still in the back-stack for a user to accidentally to go back to.

## Step-by-steps
Using backward/forward navigation in your app requires a degree of extra consideration. Users always expect the back/forward button to take them to a page that is still relevant, yet logically related to the current page and direction. This page contains several concise tutorials about how to implement navigation techniques that address these more advanced problems.

> [!IMPORTANT]
> This guide assumes you used the template wizard or `dotnet new unoapp` to create your solution. If not, it is recommended that you follow the [instructions](xref:Overview.Extensions) for creating an application from the template.
## Techniques

### 1. Navigating to a Page and Clearing Back Stack
### Navigating to a Page and Clearing Back Stack

#### From XAML

The `Navigation.Request` attribute paired with the qualifier syntax, provided by navigation Extensions, offers a powerful way to navigate to a page and then clear the back stack from XAML.

- Add an additional button to `MainPage.xaml` _without_ a click event bound to codebehind

```xml
<StackPanel Grid.Row="1"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Button AutomationProperties.AutomationId="SecondPageButton"
Content="Go to Second Page"
Click="{x:Bind ViewModel.GoToSecondPage}" />
<Button Content="Go to Second Page Clear Stack" />
</StackPanel>
```
- Add the `Navigation.Request` attached property to the button with the necessary qualifier prepended to the route

```xml
<Button Content="Go to Second Page Clear Stack"
uen:Navigation.Request="-/Second" />
```

#### From Codebehind

It is possible to navigate to a page and clear the back stack from codebehind using a more typical navigation service method such as `NavigateViewModelAsync<T>`. This can be done by specifying the `Qualifiers.ClearBackStack` qualifier.

- Add an additional button to `MainPage.xaml` with the `Click` event bound to the `GoToSecondPageClearBackStack` method

```csharp
```xml
<StackPanel Grid.Row="1"
HorizontalAlignment="Center"
VerticalAlignment="Center">
Expand All @@ -37,10 +63,33 @@ Sometimes when you navigate you don't want to leave the current page in the back

If you run the application and navigate to the `SecondPage` the back button in the `NavigationBar` isn't visible, since the frame back-stack is empty.

### 2. Navigating to a Page and Removing a Page from Back Stack
### Navigating to a Page and Removing a Page from Back Stack

Another common scenario is to navigate to a page and then remove the current page from the back stack.

#### From XAML

- Add a new `Page` to navigate to, `SamplePage.xaml`, in the UI (shared) project

- In `SecondPage.xaml` add a `Button` with the following XAML, which does _not_ include a handler for the Click event

```xml
<Button HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="Go to Sample Page" />
```

- Add the `Navigation.Request` attached property to the button with the necessary qualifier prepended to the route

```xml
<Button HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="Go to Sample Page"
uen:Navigation.Request="-Sample" />
```

#### From codebehind

- Add a new `Page` to navigate to, `SamplePage.xaml`, in the UI (shared) project
- In `SecondPage.xaml` add a `Button` with the following XAML, which includes a handler for the Click event

Expand All @@ -66,9 +115,9 @@ Another common scenario is to navigate to a page and then remove the current pag
}
```

The use of `Qualifiers.NavigateBack` will result in the `SecondPage` being removed from the back stack, after navigating forward to the `SamplePage`.
The use of qualifiers, whether from XAML or codebehind, will result in the `SecondPage` being removed from the back stack, after navigating forward to the `SamplePage`.

### 3. Navigating to Multiple Pages
### Navigating to Multiple Pages

In some cases you may want to navigate forward to a page and inject an additional page into the back stack. This can be done by specifying a multi-section route.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ uid: Learn.Tutorials.Navigation.Advanced.ResponsiveShell
---
# How-To: Build a Responsive Layout using NavigationView and TabBar

Apps that scale across multiple devices and form factors need to be able to adapt their layout to the available screen real estate. When your app is running on narrow devices, such as phones, you may want to hide the navigation pane and show a hamburger menu button instead.

It makes sense to allow `TabBar` to be the dominant navigation surface on these devices. On larger devices, such as tablets and desktops, you may want to show the navigation pane and hide the hamburger menu button. Using the `TabBar` would be a poor choice for navigation on these devices. The platform includes a `VisualStateManger` that allows you to define different visual states for different screen sizes in XAML, showing the navigation pane and hamburger menu button as appropriate.

This tutorial will show you how to build a responsive layout with multiple navigation controls such as `NavigationView` and the [Uno Toolkit](https://github.com/unoplatform/uno.toolkit.ui) `TabBar` which use the _same_ navigation service behind the scenes.

## Step-by-steps

> [!IMPORTANT]
Expand Down Expand Up @@ -360,7 +366,7 @@ While the WinUI `NavigationView` control by itself is a good choice for a respon
```
### 5. Toggle visibility for responsive design
* Finally, specify groups for the VisualStateManager to adjust the Page layout based how close the window size is to a couple of defined breakpoints:
* Finally, specify groups for the `VisualStateManager` to adjust the page layout based on how close the window size is to a couple of defined breakpoints:
```xml
<Page x:Class="ResponsiveShell.Views.MainPage">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ uid: Learn.Tutorials.Navigation.Advanced.ContentControl
---
# How-To: Use a ContentControl to Display a View

If you want to display a view in a specific location in a page, `ContentControl` is the ideal UI element. For example, you might want to display a view in a `Grid` or `StackPanel` in a specific location. You can use a `ContentControl` to display a view in a specific location.

## Step-by-steps

> [!IMPORTANT]
Expand Down
100 changes: 93 additions & 7 deletions doc/Learn/Tutorials/Navigation/Advanced/HowTo-UseNavigationView.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,102 @@ Choosing the right control for your navigation needs is important, and one commo
</Grid>
```

* Observe how the `NavigationView` and the content area are now connected. When you select a `NavigationViewItem`, the corresponding `Grid` will be shown.

* Set the `Visibility` of the `Grid` elements to `Collapsed` to hide the content area's children beforehand:

```xml
Visibility="Collapsed"
```

#### Navigating to Page elements

* You may want to navigate to a `Page` view element represented by a route name. It is possible to do this without defining the view element alongside the other content areas. For instance, you may need to display a products page `ProductsPage` which will be defined in a separate XAML file.

* Add a new **Page** item to your app called `ProductsPage` with the following code:

```xml
<Page
x:Class="UsingNavigationView.Views.ProductsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Uno.Extensions.Navigation.UI.Samples"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

<Grid>
<TextBlock Text="Products"
FontSize="24"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</Page>
```

* For the purposes for this tutorial, `ProductsPage` will be associated with its own view model `ProductsViewModel`. Add a new **Class** item to your app called `ProductsViewModel` with the following code:

```csharp
namespace UsingNavigationView.ViewModels;

public class ProductsViewModel
{
public ProductsViewModel()
{

}
}
```

* Register `ViewMap` and `RouteMap` instances inside the `RegisterRoutes` method in `App.cs`. This associates the `ProductsPage` described above with `ProductsViewModel`, as well as avoiding the use of reflection for route discovery.

```csharp
private static void RegisterRoutes(IViewRegistry views, IRouteRegistry routes)
{
views.Register(
new ViewMap<ShellControl, ShellViewModel>(),
new ViewMap<ProductsPage, ProductsViewModel>(),
new ViewMap<MainPage, MainViewModel>()
);

routes.Register(
new RouteMap("", View: views.FindByViewModel<ShellViewModel>(),
Nested: new RouteMap[]
{
new RouteMap("Main", View: views.FindByViewModel<MainViewModel>(),
Nested: new RouteMap[]
{
new RouteMap("Products", View: views.FindByViewModel<ProductsViewModel>())
})
}));
}
```

* Importantly, the snippet above establishes a route name `Products` for `ProductsPage`. We can use this route name to navigate to the `ProductsPage` view element.

* Add a `NavigationViewItem` to the `NavigationView` element with the `uen:Region.Name` attached property set to `Products`.

```xml
<NavigationView.MenuItems>
<NavigationViewItem Content="One"
uen:Region.Name="One" />
<NavigationViewItem Content="Two"
uen:Region.Name="Two" />
<NavigationViewItem Content="Three"
uen:Region.Name="Three" />
<!-- Adds a products item -->
<NavigationViewItem Content="Products"
uen:Region.Name="Products" />
</NavigationView.MenuItems>
```

### 6. Putting it all together

* Observe how the `NavigationView` and the content area are now connected. When you select a `NavigationViewItem`, the corresponding `Grid` or `Page` will be shown.

* If the route name specified represents a `Page` element, a `Frame` will be created upon navigation to host the `Page` element. This `Frame` will be added to the visual tree in order to support subsequent navigation to other `Page` elements.

* Because the navigation service maintains an instance of the view, users can leave this new `ProductsPage` to view item details and return to it _without_ losing any state such as a product filter they have already specified.

* Now, you have written a UI layout capable of navigating to views with `NavigationView`. Your completed `MainPage.xaml` should look like the code example below.

#### Code example
Expand Down Expand Up @@ -203,6 +291,8 @@ Choosing the right control for your navigation needs is important, and one commo
uen:Region.Name="Two" />
<NavigationViewItem Content="Three"
uen:Region.Name="Three" />
<NavigationViewItem Content="Products"
uen:Region.Name="Products" />
</NavigationView.MenuItems>

<Grid uen:Region.Attached="True"
Expand Down Expand Up @@ -233,8 +323,4 @@ Choosing the right control for your navigation needs is important, and one commo
</NavigationView>
</Grid>
</Page>
```

### 6. Switching between views

* To switch between views, you can now use the `NavigationView`. When you select a `NavigationViewItem`, the corresponding `Grid` will be shown. The visibility of the corresponding views will be adjusted automatically.
```
1 change: 0 additions & 1 deletion doc/Learn/Tutorials/Navigation/Advanced/HowTo-UsePanel.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
---
uid: Learn.Tutorials.Navigation.Advanced.Panel
---

# How-To: Use a Panel to Switch Views

Sometimes your application may need to switch between multiple views without the overhead of controls like `Frame` which support a navigation stack. In this case, it makes sense to define sectors of potential view content as **regions** and use another control to toggle the `Visibility` of the multiple views directly. This tutorial will show you how to use a `Panel` to switch between views.
Expand Down
Loading

0 comments on commit 8164adc

Please sign in to comment.