diff --git a/README.md b/README.md
index 03c5d83..b1c14c9 100644
--- a/README.md
+++ b/README.md
@@ -174,7 +174,7 @@ 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, go back, 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:
diff --git a/samples/DemoApp/Properties/Resources.Designer.cs b/samples/DemoApp/Properties/Resources.Designer.cs
index 91fda21..77b1ef4 100644
--- a/samples/DemoApp/Properties/Resources.Designer.cs
+++ b/samples/DemoApp/Properties/Resources.Designer.cs
@@ -258,6 +258,15 @@ internal static string Home_Button_ChangeUsernameNoAnimation {
}
}
+ ///
+ /// Looks up a localized string similar to Exit.
+ ///
+ internal static string Home_Button_Exit {
+ get {
+ return ResourceManager.GetString("Home_Button_Exit", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Flyout Page demo.
///
diff --git a/samples/DemoApp/Properties/Resources.resx b/samples/DemoApp/Properties/Resources.resx
index 632ffa6..5735660 100644
--- a/samples/DemoApp/Properties/Resources.resx
+++ b/samples/DemoApp/Properties/Resources.resx
@@ -205,6 +205,10 @@
Change Username (no animation)Translate
+
+ Exit
+ Translate
+
Flyout Page demoTranslate
diff --git a/samples/DemoApp/ViewModels/HomeViewModel.cs b/samples/DemoApp/ViewModels/HomeViewModel.cs
index 2f0b504..677c780 100644
--- a/samples/DemoApp/ViewModels/HomeViewModel.cs
+++ b/samples/DemoApp/ViewModels/HomeViewModel.cs
@@ -145,5 +145,15 @@ private async Task GoToFlyoutPageDemo()
await navigationService.Navigate($"{nameof(DemoFlyoutPage)}", navigationParameters);
}
+ ///
+ /// Exit the application.
+ ///
+ [RelayCommand]
+ private async Task Exit()
+ {
+ // Pop the homepage off the stack, closing the app.
+ await navigationService.GoBack();
+ }
+
#endregion Commands
}
diff --git a/samples/DemoApp/Views/HomePage.xaml b/samples/DemoApp/Views/HomePage.xaml
index 658cac3..25c6353 100644
--- a/samples/DemoApp/Views/HomePage.xaml
+++ b/samples/DemoApp/Views/HomePage.xaml
@@ -65,6 +65,11 @@
Command="{Binding GoToFlyoutPageDemoCommand}"
Style="{StaticResource PrimaryButton}"
Text="{x:Static properties:Resources.Home_Button_FlyoutPageDemo}" />
+
\ No newline at end of file
diff --git a/src/Burkus.Mvvm.Maui/Abstractions/INavigationService.cs b/src/Burkus.Mvvm.Maui/Abstractions/INavigationService.cs
index c63565c..c8b48b9 100644
--- a/src/Burkus.Mvvm.Maui/Abstractions/INavigationService.cs
+++ b/src/Burkus.Mvvm.Maui/Abstractions/INavigationService.cs
@@ -51,6 +51,19 @@ Task Push(NavigationParameters navigationParameters)
#region Advanced navigation methods
+ ///
+ /// Pops the top page of the navigation stack or closes the app if it is the last page.
+ ///
+ /// A completed task
+ Task GoBack();
+
+ ///
+ /// Pops the top page of the navigation stack or closes the app if it is the last page.
+ ///
+ /// Navigation parameters to pass
+ /// A completed task
+ Task GoBack(NavigationParameters navigationParameters);
+
///
/// Replace the top page of the stack with a new page.
///
diff --git a/src/Burkus.Mvvm.Maui/Models/Pages/BackButtonNavigator.cs b/src/Burkus.Mvvm.Maui/Models/Pages/BackButtonNavigator.cs
index 4199f3a..6cd06d1 100644
--- a/src/Burkus.Mvvm.Maui/Models/Pages/BackButtonNavigator.cs
+++ b/src/Burkus.Mvvm.Maui/Models/Pages/BackButtonNavigator.cs
@@ -6,7 +6,7 @@ internal static bool HandleBackButtonPressed()
{
var navigationService = ServiceResolver.Resolve();
- _ = navigationService.Pop();
+ _ = navigationService.GoBack();
// On Android and Windows, prevent the default back button behaviour
return true;
diff --git a/src/Burkus.Mvvm.Maui/Services/NavigationService.cs b/src/Burkus.Mvvm.Maui/Services/NavigationService.cs
index 00a2f86..ec4ad50 100644
--- a/src/Burkus.Mvvm.Maui/Services/NavigationService.cs
+++ b/src/Burkus.Mvvm.Maui/Services/NavigationService.cs
@@ -66,6 +66,35 @@ await HandleNavigation(async () =>
#region Advanced navigation methods
+ public async Task GoBack()
+ {
+ await GoBack(new NavigationParameters());
+ }
+
+ public async Task GoBack(NavigationParameters navigationParameters)
+ {
+ await HandleNavigation(async () =>
+ {
+ if (navigationParameters.UseModalNavigation)
+ {
+ _ = await Application.Current.MainPage.Navigation.PopModalAsync(navigationParameters.UseAnimatedNavigation);
+ }
+ else
+ {
+ if (Application.Current.MainPage.Navigation.NavigationStack.Count <= 1)
+ {
+ // quit the app as this page is the last one
+ Application.Current.Quit();
+ }
+ else
+ {
+ _ = await Application.Current.MainPage.Navigation.PopAsync(navigationParameters.UseAnimatedNavigation);
+ }
+ }
+ },
+ navigationParameters);
+ }
+
public async Task ReplaceTopPage()
where T : Page
{
diff --git a/tests/DemoApp.UnitTests/ViewModels/HomeViewModelTests.cs b/tests/DemoApp.UnitTests/ViewModels/HomeViewModelTests.cs
index d1657fe..efca34b 100644
--- a/tests/DemoApp.UnitTests/ViewModels/HomeViewModelTests.cs
+++ b/tests/DemoApp.UnitTests/ViewModels/HomeViewModelTests.cs
@@ -124,4 +124,17 @@ public void AddMultiplePagesCommand_WhenCalled_NavigatesToSeveralPages()
// Assert
mockNavigationService.Received().Navigate("DemoTabsPage/RegisterPage/UriTestPage");
}
+
+ [Fact]
+ public void ExitCommand_WhenCalled_ClosesTheApp()
+ {
+ // Arrange
+ var viewModel = ViewModel;
+
+ // Act
+ viewModel.ExitCommand.Execute(null);
+
+ // Assert
+ mockNavigationService.Received().GoBack();
+ }
}
\ No newline at end of file