Chinook.StackNavigation.Reactive
0.7.0
See the version list below for details.
dotnet add package Chinook.StackNavigation.Reactive --version 0.7.0
NuGet\Install-Package Chinook.StackNavigation.Reactive -Version 0.7.0
<PackageReference Include="Chinook.StackNavigation.Reactive" Version="0.7.0" />
paket add Chinook.StackNavigation.Reactive --version 0.7.0
#r "nuget: Chinook.StackNavigation.Reactive, 0.7.0"
// Install Chinook.StackNavigation.Reactive as a Cake Addin #addin nuget:?package=Chinook.StackNavigation.Reactive&version=0.7.0 // Install Chinook.StackNavigation.Reactive as a Cake Tool #tool nuget:?package=Chinook.StackNavigation.Reactive&version=0.7.0
Chinook StackNavigation and SectionsNavigation
This library provides unified cross-platform tools to perform ViewModel-based navigation using the Frame navigation model.
// Navigate to the PersonDetailsPage.
await navigator.Navigate(ct, () => new PersonDetailsPageViewModel());
// Navigate back.
await navigator.NavigateBack(ct);
Getting Started
1. Choose your Navigator
There are 2 types of navigators available:
IStackNavigator
- Use this if your app would use a singleFrame
.ISectionsNavigator
- Use this if you want to use multiple frames (like sections tabs) or modals. Note thatIStackNavigator
is used as a building block byISectionsNavigator
.
2. Create your Navigator
See how to get you instance for StackNavigation or SectionsNavigation. Note that your code should always use the interface in order to be easily reused for integration tests.
3. Use your Navigator
There's a lot of things you can do. Here are some examples.
Navigate forward and back
// Navigate to the PersonDetailsPage.
await navigator.Navigate(ct, () => new PersonDetailsPageViewModel());
// Navigate back.
await navigator.NavigateBack(ct);
Navigate forward, clearing the backstack
// Navigate to the HomePage, clearing all other previous pages from the backstack.
await navigator.NavigateAndClear(ct, () => new HomePageViewModel());
Remove previous pages
// Navigate to Step 1
await navigator.Navigate(ct, () => new Step1PageViewModel());
// Navigate to Step 2
await navigator.Navigate(ct, () => new Step2PageViewModel());
// Navigate to Step 2.1
await navigator.Navigate(ct, () => new Step21PageViewModel());
// Navigate to Step 3
await navigator.Navigate(ct, () => new Step3PageViewModel());
// Remove the previous page (Step 2.1) from the backstack.
await navigator.RemovePrevious(ct);
// Navigate back to Step 2
await navigator.NavigateBack(ct);
The following examples only apply to ISectionsNavigator
.
Change between sections
// Go to Home section.
await sectionsNavigator.SetActiveSection(ct, "Home");
// Go to Messages section.
await sectionsNavigator.SetActiveSection(ct, "Messages");
// Go to Settings section.
await sectionsNavigator.SetActiveSection(ct, "Settings");
Return to root of section
// Go to Home section.
await sectionsNavigator.SetActiveSection(ct, "Home", () => new HomePageViewModel());
// Navigate forward to some details page in the Home section.
await sectionsNavigator.Navigate(ct, () => new PersonDetailsPageViewModel());
// Go to Messages section.
await sectionsNavigator.SetActiveSection(ct, "Messages");
// Return to Home section on the Home page, not the PersonDetails page.
await sectionsNavigator.SetActiveSection(ct, "Home", () => new HomePageViewModel(), returnToRoot: true);
Open and close modals
// Open LoginPage in a modal.
await sectionsNavigator.OpenModal(ct, () => new LoginPageViewModel());
// Close the modal.
await sectionsNavigator.CloseModal(ct);
Open modals behind other modals
// Open LoginPage in a modal with a priority of 2.
await sectionsNavigator.OpenModal(ct, () => new LoginPageViewModel(), priority = 2);
// Open the SurveyPage in a modal behind the LoginPage page modal, using a lower priority of 1.
// Because the SurveyPage opens with a lower priority, you don't actually see this change happen.
await sectionsNavigator.OpenModal(ct, () => new SurveyPageViewModel(), priority = 1);
// Close the top-most modal (LoginPage) to reveal the SurveyPage modal behind it.
await sectionsNavigator.CloseModal(ct);
Change sections behind modals
// Open LoginPage in a modal.
await sectionsNavigator.OpenModal(ct, () => new LoginPageViewModel());
// Change the section to Messages.
// Modals are displayed on top of sections, so you don't actually see this change happen.
await sectionsNavigator.SetActiveSection(ct, "Messages", () => new MessagesPageViewModel());
// Close the modal to reveal the Messages section.
await sectionsNavigator.CloseModal(ct);
Navigate in an inactive section
// Go to Home section.
await sectionsNavigator.SetActiveSection(ct, "Home", () => new HomePageViewModel());
// Get the settings section navigator.
var settingsSection = sectionsNavigator.State.Sections["Settings"];
// Navigate forward to the SettingsPage, then the LicencePage in the Settings section.
// The Settings sections is not currently active, so you don't actually see this change happen.
await settingsSection.Navigate(ct, () => new SettingsPageViewModel());
await settingsSection.Navigate(ct, () => new LicencePageViewModel());
// Go to Settings section to see the Licence page.
await sectionsNavigator.SetActiveSection(ct, "Settings");
// Navigate back to SettingsPage.
await sectionsNavigator.NavigateBack(ct);
Navigate back or close modal
// Check whether the navigator can navigate back or close a modal.
// This us useful when dealing with an hardware back button.
if (sectionsNavigator.CanNavigateBackOrCloseModal())
{
// Navigates back within the modal if the modal has multiple pages in its stack
// Or closes the modal if there's a modal that has an empty backstack
// Or navigates back in the active section.
await sectionsNavigator.NavigateBackOrCloseModal(ct);
}
Features
Ready for Dependency Injection
The two navigation services are made from simple interfaces. You can easily leverage containers such as Microsoft's Generic Host.
Ready for Integration Testing
Because this is ViewModel-based navigation and the navigator interfaces don't reference any UI type, you can use the navigators in Test Projects or Console Applications without changing your navigation logic. Just install the Chinook.SectionsNavigation
or Chinook.StackNavigation
packages and use the BlindSectionsNavigator
or BlindStackNavigator
implementations.
No Double Navigation
If you invoke 2 operations simultaneously (double tap, press 2 buttons with 2 fingers, etc.), only the first will actually run.
This is because the request state (Processing, Processed or FailedToProcess) is part of the ISectionsNavigator.State
.
If a request is made while another is processing, the second request is cancelled.
Background Navigation
You can navigate in sections that are not active. This is useful if you want to prepare a section before entering it.
Transitions and Animations
For stack navigation, you can suppress the default transition using StackNavigatorRequest.SuppressTransitions
.
For sections navigation, you can customize or disable animations using SectionsNavigatorRequest.TransitionInfo
.
You can read more on that here.
Modals
ISectionsNavigator
allows you to handle multiple stacks of navigation in your app, including modals. This means you can easily handle navigation with your modals, since the modals are just in another navigation stack. For instance, the user can navigate back and forth in the modals, and your app can navigate the pages behind the modals, without breaking the flow.
Changelog
Please consult the CHANGELOG for more information about version history.
License
This project is licensed under the Apache 2.0 license - see the LICENSE file for details.
Contributing
Please read CONTRIBUTING.md for details on the process for contributing to this project.
Be mindful of our Code of Conduct.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Chinook.StackNavigation.Abstractions (>= 0.7.0)
- System.Reactive (>= 4.4.1)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Chinook.StackNavigation.Reactive:
Package | Downloads |
---|---|
Chinook.SectionsNavigation.Reactive
Unified cross-platform tools to perform ViewModel-based navigation. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
3.0.2 | 2,451 | 2/22/2024 |
3.0.1 | 8,130 | 1/18/2024 |
3.0.0 | 1,404 | 12/22/2023 |
3.0.0-feature.Uno5Update.7 | 150 | 12/6/2023 |
3.0.0-feature.Uno5Update.4 | 1,805 | 11/28/2023 |
2.1.2 | 6,420 | 2/22/2024 |
2.1.1 | 10,232 | 6/15/2023 |
2.1.0 | 437 | 6/15/2023 |
2.0.0 | 14,303 | 4/12/2023 |
1.1.2 | 60,105 | 10/14/2022 |
1.1.1 | 685 | 10/12/2022 |
1.1.0 | 2,549 | 9/23/2022 |
1.1.0-feature.dotnet6.12 | 149 | 9/22/2022 |
1.1.0-feature.dotnet6.4 | 132 | 9/16/2022 |
1.0.0 | 3,465 | 9/2/2022 |
0.7.0 | 731 | 8/30/2022 |
0.7.0-dev.91 | 14,693 | 5/17/2022 |
0.7.0-dev.88 | 13,998 | 4/13/2022 |
0.7.0-dev.86 | 176 | 4/12/2022 |
0.7.0-dev.83 | 297 | 3/30/2022 |
0.6.0-feature.uno-ui-4.79 | 175 | 3/15/2022 |
0.6.0-feature.uno-ui-4.78 | 158 | 3/15/2022 |
0.6.0-dev.80 | 315 | 3/15/2022 |
0.5.0-feature.uno-ui-4.77 | 7,729 | 1/25/2022 |
0.5.0-dev.73 | 10,941 | 1/24/2022 |
0.5.0-dev.71 | 154 | 1/20/2022 |
0.4.0-feature.uno-ui-4.70 | 208 | 12/20/2021 |
0.4.0-dev.69 | 10,023 | 10/12/2021 |
0.4.0-dev.67 | 34,771 | 5/26/2021 |
0.4.0-dev.65 | 263 | 4/20/2021 |
0.4.0-dev.62 | 1,681 | 4/19/2021 |
0.4.0-dev.59 | 8,975 | 4/6/2021 |
0.3.0-dev.53 | 226 | 3/30/2021 |
0.3.0-dev.50 | 7,995 | 3/16/2021 |
0.2.0-dev.46 | 1,603 | 12/17/2020 |
0.2.0-dev.44 | 5,401 | 12/4/2020 |
0.2.0-dev.42 | 291 | 12/4/2020 |
0.2.0-dev.39 | 321 | 11/2/2020 |
0.2.0-dev.37 | 9,339 | 8/21/2020 |
0.2.0-dev.33 | 5,346 | 8/13/2020 |
0.2.0-dev.31 | 333 | 6/26/2020 |
0.2.0-dev.29 | 312 | 6/26/2020 |