Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial Uri navigation #23

Merged
merged 21 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CONTRIBUTING.MD
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,5 @@ NOTE: The above software is the recommended basics. You may be able to use other
## Submitting a PR
- Try to rebase (`git rebase -i`) your PR onto `main` to tidy your git history https://www.atlassian.com/git/tutorials/rewriting-history/git-rebase
- Update the unit tests (fix any existing tests and ensure new code has unit test coverage)
- Update the sample app with the change/feature in action
- Ensure you have the [XAML Styler](https://marketplace.visualstudio.com/items?itemName=TeamXavalon.XAMLStyler2022) extension installed and have run it on any XAML files you have changed to format them
70 changes: 62 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ ServiceResolver.Resolve(IExampleService);
```

## Navigation service
`INavigationService` is automatically registered by `.UseBurkusMvvm(...)`. You can use it to: push pages, pop pages, pop to the root page, replace the top page of the app, reset the navigation stack, switch tabs, and more.
`INavigationService` is automatically registered by `.UseBurkusMvvm(...)`. You can use it to: push pages, pop pages, pop to the root page, replace the top page of the app, reset the navigation stack, switch tabs, and more.
See the [INavigationService interface in the repository](https://github.com/BurkusCat/Burkus.Mvvm.Maui/blob/main/src/Abstractions/INavigationService.cs) for all possible navigation method options.

This is a simple navigation example where we push a "`TestPage`" onto the navigation stack:
``` csharp
Expand All @@ -164,7 +165,7 @@ var navigationParameters = new NavigationParameters
{ "username", Username },
};

// 2. append an additional custom parameter
// 2. append an additional, custom parameter
navigationParameters.Add("selection", Selection);

// 3. reserved parameter with a special meaning in the Burkus MVVM library, it has a helper method to make setting it easier
Expand All @@ -173,7 +174,55 @@ navigationParameters.UseModalNavigation = true;
await navigationService.Push<TestPage>(navigationParameters);
```

See the [INavigationService interface in the repository](https://github.com/BurkusCat/Burkus.Mvvm.Maui/blob/main/src/Abstractions/INavigationService.cs) for all possible navigation method options.
The `INavigationService` supports URI/URL-based navigation. Use the `.Navigate(string uri)` or `.Navigate(string uri, NavigationParameters navigationParameters)` methods to do more complex navigation.

**⚠️ WARNING**: URI-based navigation behavior is unstable and is likely to change in future releases. Passing parameters, events triggered etc. are all inconsistent at present.

Here are some examples of URI navigation:
``` csharp
// use absolute navigation (starts with a "/") to go to the LoginPage
navigationService.Navigate("/LoginPage");

// push multiple pages using relative navigation onto the stack
navigationService.Navigate("AlphaPage/BetaPage/CharliePage");

// push a page relatively with query parameters
navigationService.Navigate("HomePage?username=Ronan&loggedIn=True");

// push a page with query parameters *and* navigation parameters
// - the query parameters only apply to one segment
// - the navigation parameters apply to the entire navigation
// - query parameters override navigation parameters
var parameters = new NavigationParameters { "example", 456 };
navigationService.Navigate("ProductPage?productid=123", parameters);

// go back one page modally
var parameters = new NavigationParameters();
parameters.UseModalNavigation = true;
navigationService.Navigate("..", parameters);

// go back three pages and push one new page
navigationService.Navigate("../../../AlphaPage");

// it is good practice to use nameof(x) to provide a compile-time reference to the pages in your navigation
navigationService.Navigate($"{nameof(YankeePage)}/{nameof(ZuluPage)}");
```
### Navigation URI builder
Navigation to multiple pages simultaneously and passing parameters to them can start to get complicated quickly. The `NavigationUriBuilder` is a simple, typed way to build a complex navigation string.

Below is an example where we go back a page (and pass a parameter that instructs the navigation to be performed modally), then push a `VictorPage`, and then push a `YankeePage` modally onto the stack:
``` csharp
var parameters = new NavigationParameters();
parameters.UseModalNavigation = true;

var navigationUri = new NavigationUriBuilder()
.AddGoBackSegment(parameters)
.AddSegment<VictorPage>()
.AddSegment<YankeePage>(parameters)
.Build() // produces the string: "..?UseModalNavigation=True/VictorPage/YankeePage/"

navigationService.Navigate(navigationUri);
```

## Choosing the start page of your app
It is possible to have a service that decides which page is most appropriate to navigate to. This service could decide to:
Expand Down Expand Up @@ -236,11 +285,17 @@ If your viewmodel inherits from this interface, the below events will trigger fo
Several parameter keys have been pre-defined and are using by the `Burkus.Mvvm.Maui` library to adjust how navigation is performed.

- `ReservedNavigationParameters.UseAnimatedNavigation`
- Should an animation be used during the navigation?
- Defaults to: `true`
- If true, uses an animation during navigation.
- Type: `bool`
- Default: `true`
- `ReservedNavigationParameters.UseModalNavigation`
- Should the navigation be performed modally?
- Defaults to: `false`
- If true, performs the navigation modally.
- Type: `bool`
- Default: `false`
- `ReservedNavigationParameters.SelectTab`
- If navigating to a `TabbedPage`, selects the tab with the name of the type passed. **⚠️ WARNING**: Not yet implemented.
- Type: `string`
- Default: `null`

The `NavigationParameters` object exposes some handy properties `.UseAnimatedNavigation` and `.UseModalNavigation` so you can easily set or check the value of these properties.

Expand Down Expand Up @@ -274,7 +329,6 @@ The below are some things of note that may help prevent issues from arising:
- When you inherit from `BurkusMvvmApplication`, the `MainPage` of the app will be automatically set to a `NavigationPage`. This means the first page you push can be a `ContentPage` rather than needing to push a `NavigationPage`. This may change in the future.

# Roadmap 🛣️
- [URL-based navigation](https://github.com/BurkusCat/Burkus.Mvvm.Maui/issues/1)
- [View and viewmodel auto-registration](https://github.com/BurkusCat/Burkus.Mvvm.Maui/issues/4)
- [Popup pages](https://github.com/BurkusCat/Burkus.Mvvm.Maui/issues/2)
- [Nested viewmodels](https://github.com/BurkusCat/Burkus.Mvvm.Maui/issues/5)
Expand Down
5 changes: 3 additions & 2 deletions SECURITY.MD
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ The latest version of the package only will be supported with security fixes. If
| < 0.1 | :x: |

## Reporting a Vulnerability

Get in touch with @BurkusCat on Twitter/X. After making contact communicate via Direct Messages to disclose the vulnerability.
Contact options:
- Go to https://www.nuget.org/packages/Burkus.Mvvm.Maui and press the "Contact owners"
- Get in touch with @BurkusCat on Twitter/X. After making contact, communicate via Direct Messages to disclose the vulnerability.
1 change: 1 addition & 0 deletions samples/DemoApp/App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Styles/Colors.xaml" />
<ResourceDictionary Source="Resources/Styles/DemoAppStyles.xaml" />
<ResourceDictionary Source="Resources/Styles/Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Expand Down
9 changes: 9 additions & 0 deletions samples/DemoApp/DemoApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@
<Compile Update="Views\ChangeUsernamePage.xaml.cs">
<DependentUpon>ChangeUsernamePage.xaml</DependentUpon>
</Compile>
<Compile Update="Views\UriTestPage.xaml.cs">
<DependentUpon>UriTestPage.xaml</DependentUpon>
</Compile>
<Compile Update="Views\Tabs\CharlieTabPage.xaml.cs">
<DependentUpon>CharlieTabPage.xaml</DependentUpon>
</Compile>
Expand All @@ -90,12 +93,18 @@
</ItemGroup>

<ItemGroup>
<MauiXaml Update="Resources\Styles\DemoAppStyles.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="Views\ChangeUsernamePage.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</MauiXaml>
<MauiXaml Update="Views\HomePage.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</MauiXaml>
<MauiXaml Update="Views\UriTestPage.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</MauiXaml>
<MauiXaml Update="Views\Tabs\CharlieTabPage.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</MauiXaml>
Expand Down
2 changes: 2 additions & 0 deletions samples/DemoApp/MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public static MauiAppBuilder RegisterViewModels(this MauiAppBuilder mauiAppBuild
mauiAppBuilder.Services.AddTransient<HomeViewModel>();
mauiAppBuilder.Services.AddTransient<LoginViewModel>();
mauiAppBuilder.Services.AddTransient<RegisterViewModel>();
mauiAppBuilder.Services.AddTransient<UriTestViewModel>();

return mauiAppBuilder;
}
Expand All @@ -54,6 +55,7 @@ public static MauiAppBuilder RegisterViews(this MauiAppBuilder mauiAppBuilder)
mauiAppBuilder.Services.AddTransient<HomePage>();
mauiAppBuilder.Services.AddTransient<LoginPage>();
mauiAppBuilder.Services.AddTransient<RegisterPage>();
mauiAppBuilder.Services.AddTransient<UriTestPage>();

return mauiAppBuilder;
}
Expand Down
Loading
Loading