diff --git a/11.0/Navigation/ShellRouteTemplates/README.md b/11.0/Navigation/ShellRouteTemplates/README.md
new file mode 100644
index 000000000..2afb3011f
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/README.md
@@ -0,0 +1,81 @@
+---
+name: .NET MAUI - Shell route templates
+description: Demonstrates absolute Shell navigation with required, optional, defaulted, constrained, catch-all, and mixed route-template parameters.
+page_type: sample
+languages:
+- csharp
+- xaml
+products:
+- dotnet-maui
+urlFragment: navigation-shell-route-templates
+---
+
+# Shell route templates
+
+This .NET MAUI 11 sample is a small trip-planning route lab. Its route matrix runs every route-template form introduced by [dotnet/maui#35110](https://github.com/dotnet/maui/pull/35110), navigates to a result page, and compares the delivered parameter with the expected value.
+
+> [!IMPORTANT]
+> Route templates support **absolute navigation only** in this release. Every example uses a URI beginning with `//routes`. Do not use these templates with relative navigation.
+
+## What you'll learn
+
+- How to register required, optional, defaulted, constrained, catch-all, and mixed route templates.
+- Which constraints are implemented by the shipping parser.
+- How path parameters flow through both `[QueryProperty]` and `IQueryAttributable`.
+- How to verify the resolved value on the destination page.
+
+## Requirements
+
+- .NET SDK `11.0.100-preview.7.26381.103`
+- .NET MAUI workload
+- .NET MAUI `11.0.0-preview.7.26404.4`, supplied by `11.0/Directory.Build.props`
+- Android, iOS, or Mac Catalyst tooling for the target you run
+
+## Route matrix
+
+Optional and default parameters must be the final segment. Catch-all parameters must also be last. The shipping implementation supports one parameter per mixed segment and one constraint per parameter.
+
+| Form | Registered template | Absolute URI used by the sample | Delivered value |
+|---|---|---|---|
+| Required | `trip/{tripId}` | `//routes/trip/SEA-204` | `tripId = SEA-204` |
+| Optional, present | `traveler/{name?}` | `//routes/traveler/Ada` | `name = Ada` |
+| Optional, absent | `traveler/{name?}` | `//routes/traveler` | `name` is not supplied |
+| Default | `rating/{stars=5}` | `//routes/rating` | `stars = 5` |
+| `int` constraint | `reservation/{reservationId:int}` | `//routes/reservation/42` | `reservationId = 42` |
+| `long` constraint | `loyalty/{points:long}` | `//routes/loyalty/9000000000` | `points = 9000000000` |
+| `double` constraint | `budget/{amount:double}` | `//routes/budget/1299.50` | `amount = 1299.50` |
+| `bool` constraint | `toggle/{enabled:bool}` | `//routes/toggle/true` | `enabled = true` |
+| `guid` constraint | `booking/{reference:guid}` | `//routes/booking/550e8400-e29b-41d4-a716-446655440000` | `reference` is the GUID |
+| `alpha` constraint | `region/{name:alpha}` | `//routes/region/Pacific` | `name = Pacific` |
+| Catch-all | `files/{*path}` | `//routes/files/trips/SEA-204/receipt.pdf` | `path = trips/SEA-204/receipt.pdf` |
+| Mixed segment | `trip-{tripId}-summary` | `//routes/trip-SEA-204-summary` | `tripId = SEA-204` |
+
+The app appends a `caseId` query string solely to select the expected matrix row. The values shown above come from the path template.
+
+## Key files
+
+| File | Purpose |
+|---|---|
+| `src/AppShell.xaml.cs` | Registers each route template. |
+| `src/Models/RouteCatalog.cs` | Defines the testable route matrix and expected values. |
+| `src/ViewModels/MainPageViewModel.cs` | Executes each absolute navigation URI. |
+| `src/QueryPropertyResultPage.xaml.cs` | Receives required and mixed parameters through `[QueryProperty]`. |
+| `src/AttributableResultPage.xaml.cs` | Receives the other parameters through `IQueryAttributable`. |
+
+## Run the sample
+
+From this directory:
+
+```bash
+dotnet build src/ShellRouteTemplates.sln
+dotnet build -t:Run -f net11.0-maccatalyst src/ShellRouteTemplates.csproj
+```
+
+You can also select the `net11.0-ios` target and an iOS simulator in Visual Studio Code or Visual Studio. On the route matrix, choose **Run** for each row. The destination page displays `PASS` when the actual path parameter matches the expected value.
+
+## Resources
+
+- [Feature PR: Shell route templates with path parameters](https://github.com/dotnet/maui/pull/35110)
+- [Shipping route-template parser](https://github.com/dotnet/maui/blob/e45600b065c6636c73fefdc8406bf8881f65e9d4/src/Controls/src/Core/Shell/RouteTemplate.cs)
+- [Shipping route-template tests](https://github.com/dotnet/maui/blob/e45600b065c6636c73fefdc8406bf8881f65e9d4/src/Controls/tests/Core.UnitTests/ShellRouteTemplatesTests.cs)
+- [.NET MAUI for .NET 11 release notes](https://learn.microsoft.com/dotnet/maui/whats-new/dotnet-11?view=net-maui-11.0)
diff --git a/11.0/Navigation/ShellRouteTemplates/src/App.xaml b/11.0/Navigation/ShellRouteTemplates/src/App.xaml
new file mode 100644
index 000000000..220dd7cdb
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/App.xaml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/11.0/Navigation/ShellRouteTemplates/src/App.xaml.cs b/11.0/Navigation/ShellRouteTemplates/src/App.xaml.cs
new file mode 100644
index 000000000..174400fb5
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/App.xaml.cs
@@ -0,0 +1,17 @@
+namespace ShellRouteTemplates;
+
+public partial class App : Application
+{
+ readonly AppShell appShell;
+
+ public App(AppShell appShell)
+ {
+ InitializeComponent();
+ this.appShell = appShell;
+ }
+
+ protected override Window CreateWindow(IActivationState? activationState)
+ {
+ return new Window(appShell);
+ }
+}
diff --git a/11.0/Navigation/ShellRouteTemplates/src/AppShell.xaml b/11.0/Navigation/ShellRouteTemplates/src/AppShell.xaml
new file mode 100644
index 000000000..902964074
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/AppShell.xaml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/11.0/Navigation/ShellRouteTemplates/src/AppShell.xaml.cs b/11.0/Navigation/ShellRouteTemplates/src/AppShell.xaml.cs
new file mode 100644
index 000000000..ac57fc245
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/AppShell.xaml.cs
@@ -0,0 +1,22 @@
+namespace ShellRouteTemplates;
+
+public partial class AppShell : Shell
+{
+ public AppShell(MainPage mainPage)
+ {
+ InitializeComponent();
+ RouteMatrix.Content = mainPage;
+
+ Routing.RegisterRoute("trip/{tripId}", typeof(RequiredResultPage));
+ Routing.RegisterRoute("traveler/{name?}", typeof(TravelerResultPage));
+ Routing.RegisterRoute("rating/{stars=5}", typeof(DefaultValueResultPage));
+ Routing.RegisterRoute("reservation/{reservationId:int}", typeof(IntConstraintResultPage));
+ Routing.RegisterRoute("loyalty/{points:long}", typeof(LongConstraintResultPage));
+ Routing.RegisterRoute("budget/{amount:double}", typeof(DoubleConstraintResultPage));
+ Routing.RegisterRoute("toggle/{enabled:bool}", typeof(BoolConstraintResultPage));
+ Routing.RegisterRoute("booking/{reference:guid}", typeof(GuidConstraintResultPage));
+ Routing.RegisterRoute("region/{name:alpha}", typeof(AlphaConstraintResultPage));
+ Routing.RegisterRoute("files/{*path}", typeof(CatchAllResultPage));
+ Routing.RegisterRoute("trip-{tripId}-summary", typeof(MixedResultPage));
+ }
+}
diff --git a/11.0/Navigation/ShellRouteTemplates/src/AttributableResultPage.xaml b/11.0/Navigation/ShellRouteTemplates/src/AttributableResultPage.xaml
new file mode 100644
index 000000000..04171995a
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/AttributableResultPage.xaml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/11.0/Navigation/ShellRouteTemplates/src/AttributableResultPage.xaml.cs b/11.0/Navigation/ShellRouteTemplates/src/AttributableResultPage.xaml.cs
new file mode 100644
index 000000000..5b51e3e2d
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/AttributableResultPage.xaml.cs
@@ -0,0 +1,87 @@
+using ShellRouteTemplates.Models;
+
+namespace ShellRouteTemplates;
+
+public partial class AttributableResultPage : ContentPage, IQueryAttributable
+{
+ protected AttributableResultPage()
+ {
+ InitializeComponent();
+ }
+
+ public void ApplyQueryAttributes(IDictionary query)
+ {
+ var caseId = query.TryGetValue("caseId", out var caseValue)
+ ? caseValue?.ToString()
+ : null;
+ var example = RouteCatalog.Find(caseId);
+ var actualValue = example is not null
+ && query.TryGetValue(example.ParameterName, out var parameterValue)
+ ? parameterValue?.ToString()
+ : null;
+ var actualLabel = new Label();
+ var statusLabel = new Label
+ {
+ FontAttributes = FontAttributes.Bold,
+ FontSize = 24
+ };
+
+ if (example is not null)
+ {
+ actualLabel.AutomationId = $"ActualValue-{example.Id}";
+ statusLabel.AutomationId = $"ResultStatus-{example.Id}";
+ }
+
+ ActualValueHost.Content = actualLabel;
+ StatusHost.Content = statusLabel;
+
+ RouteResultView.Render(
+ example,
+ actualValue,
+ FormLabel,
+ TemplateLabel,
+ DeliveryLabel,
+ ExpectedLabel,
+ actualLabel,
+ statusLabel);
+ }
+
+ async void OnBackToMatrix(object? sender, EventArgs e) =>
+ await Shell.Current.GoToAsync("//routes");
+}
+
+public sealed class TravelerResultPage : AttributableResultPage
+{
+}
+
+public sealed class DefaultValueResultPage : AttributableResultPage
+{
+}
+
+public sealed class IntConstraintResultPage : AttributableResultPage
+{
+}
+
+public sealed class LongConstraintResultPage : AttributableResultPage
+{
+}
+
+public sealed class DoubleConstraintResultPage : AttributableResultPage
+{
+}
+
+public sealed class BoolConstraintResultPage : AttributableResultPage
+{
+}
+
+public sealed class GuidConstraintResultPage : AttributableResultPage
+{
+}
+
+public sealed class AlphaConstraintResultPage : AttributableResultPage
+{
+}
+
+public sealed class CatchAllResultPage : AttributableResultPage
+{
+}
diff --git a/11.0/Navigation/ShellRouteTemplates/src/MainPage.xaml b/11.0/Navigation/ShellRouteTemplates/src/MainPage.xaml
new file mode 100644
index 000000000..602b9ec79
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/MainPage.xaml
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/11.0/Navigation/ShellRouteTemplates/src/MainPage.xaml.cs b/11.0/Navigation/ShellRouteTemplates/src/MainPage.xaml.cs
new file mode 100644
index 000000000..14fdb5932
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/MainPage.xaml.cs
@@ -0,0 +1,12 @@
+using ShellRouteTemplates.ViewModels;
+
+namespace ShellRouteTemplates;
+
+public partial class MainPage : ContentPage
+{
+ public MainPage(MainPageViewModel viewModel)
+ {
+ InitializeComponent();
+ BindingContext = viewModel;
+ }
+}
diff --git a/11.0/Navigation/ShellRouteTemplates/src/MauiProgram.cs b/11.0/Navigation/ShellRouteTemplates/src/MauiProgram.cs
new file mode 100644
index 000000000..b5c3e45d6
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/MauiProgram.cs
@@ -0,0 +1,29 @@
+using Microsoft.Extensions.Logging;
+using ShellRouteTemplates.ViewModels;
+
+namespace ShellRouteTemplates;
+
+public static class MauiProgram
+{
+ public static MauiApp CreateMauiApp()
+ {
+ var builder = MauiApp.CreateBuilder();
+ builder
+ .UseMauiApp()
+ .ConfigureFonts(fonts =>
+ {
+ fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
+ fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
+ });
+
+ builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
+
+#if DEBUG
+ builder.Logging.AddDebug();
+#endif
+
+ return builder.Build();
+ }
+}
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Models/RouteCatalog.cs b/11.0/Navigation/ShellRouteTemplates/src/Models/RouteCatalog.cs
new file mode 100644
index 000000000..08412eb41
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Models/RouteCatalog.cs
@@ -0,0 +1,25 @@
+namespace ShellRouteTemplates.Models;
+
+public static class RouteCatalog
+{
+ public const string NotSupplied = "(not supplied)";
+
+ public static IReadOnlyList Examples { get; } =
+ [
+ new("required", "Required parameter", "trip/{tripId}", "//routes/trip/SEA-204?caseId=required", "QueryProperty", "tripId", "SEA-204", "A trip identifier is required."),
+ new("optional-present", "Optional parameter (present)", "traveler/{name?}", "//routes/traveler/Ada?caseId=optional-present", "IQueryAttributable", "name", "Ada", "The final segment can be supplied."),
+ new("optional-absent", "Optional parameter (absent)", "traveler/{name?}", "//routes/traveler?caseId=optional-absent", "IQueryAttributable", "name", NotSupplied, "The final segment can be omitted."),
+ new("default", "Default value", "rating/{stars=5}", "//routes/rating?caseId=default", "IQueryAttributable", "stars", "5", "An omitted final segment delivers its default."),
+ new("constraint-int", "Constraint: int", "reservation/{reservationId:int}", "//routes/reservation/42?caseId=constraint-int", "IQueryAttributable", "reservationId", "42", "Accepts a 32-bit integer."),
+ new("constraint-long", "Constraint: long", "loyalty/{points:long}", "//routes/loyalty/9000000000?caseId=constraint-long", "IQueryAttributable", "points", "9000000000", "Accepts a 64-bit integer."),
+ new("constraint-double", "Constraint: double", "budget/{amount:double}", "//routes/budget/1299.50?caseId=constraint-double", "IQueryAttributable", "amount", "1299.50", "Accepts an invariant-culture number."),
+ new("constraint-bool", "Constraint: bool", "toggle/{enabled:bool}", "//routes/toggle/true?caseId=constraint-bool", "IQueryAttributable", "enabled", "true", "Accepts true or false."),
+ new("constraint-guid", "Constraint: guid", "booking/{reference:guid}", "//routes/booking/550e8400-e29b-41d4-a716-446655440000?caseId=constraint-guid", "IQueryAttributable", "reference", "550e8400-e29b-41d4-a716-446655440000", "Accepts a GUID."),
+ new("constraint-alpha", "Constraint: alpha", "region/{name:alpha}", "//routes/region/Pacific?caseId=constraint-alpha", "IQueryAttributable", "name", "Pacific", "Accepts letters only."),
+ new("catch-all", "Catch-all", "files/{*path}", "//routes/files/trips/SEA-204/receipt.pdf?caseId=catch-all", "IQueryAttributable", "path", "trips/SEA-204/receipt.pdf", "Captures all remaining path segments."),
+ new("mixed", "Mixed literal and parameter", "trip-{tripId}-summary", "//routes/trip-SEA-204-summary?caseId=mixed", "QueryProperty", "tripId", "SEA-204", "Matches a parameter between literal text.")
+ ];
+
+ public static RouteExample? Find(string? id) =>
+ Examples.FirstOrDefault(example => example.Id == id);
+}
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Models/RouteExample.cs b/11.0/Navigation/ShellRouteTemplates/src/Models/RouteExample.cs
new file mode 100644
index 000000000..959587170
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Models/RouteExample.cs
@@ -0,0 +1,14 @@
+namespace ShellRouteTemplates.Models;
+
+public sealed record RouteExample(
+ string Id,
+ string Form,
+ string Template,
+ string NavigationUri,
+ string Delivery,
+ string ParameterName,
+ string ExpectedValue,
+ string Summary)
+{
+ public string AutomationId => $"Route-{Id}";
+}
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Platforms/Android/AndroidManifest.xml b/11.0/Navigation/ShellRouteTemplates/src/Platforms/Android/AndroidManifest.xml
new file mode 100644
index 000000000..ddd284fbc
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Platforms/Android/AndroidManifest.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Platforms/Android/MainActivity.cs b/11.0/Navigation/ShellRouteTemplates/src/Platforms/Android/MainActivity.cs
new file mode 100644
index 000000000..ca3e9c462
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Platforms/Android/MainActivity.cs
@@ -0,0 +1,10 @@
+using Android.App;
+using Android.Content.PM;
+using Android.OS;
+
+namespace ShellRouteTemplates;
+
+[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
+public class MainActivity : MauiAppCompatActivity
+{
+}
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Platforms/Android/MainApplication.cs b/11.0/Navigation/ShellRouteTemplates/src/Platforms/Android/MainApplication.cs
new file mode 100644
index 000000000..f5b4688fc
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Platforms/Android/MainApplication.cs
@@ -0,0 +1,15 @@
+using Android.App;
+using Android.Runtime;
+
+namespace ShellRouteTemplates;
+
+[Application]
+public class MainApplication : MauiApplication
+{
+ public MainApplication(IntPtr handle, JniHandleOwnership ownership)
+ : base(handle, ownership)
+ {
+ }
+
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+}
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Platforms/Android/Resources/values/colors.xml b/11.0/Navigation/ShellRouteTemplates/src/Platforms/Android/Resources/values/colors.xml
new file mode 100644
index 000000000..fbaa64a5a
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Platforms/Android/Resources/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #512BD4
+ #2B0B98
+ #2B0B98
+
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Platforms/MacCatalyst/AppDelegate.cs b/11.0/Navigation/ShellRouteTemplates/src/Platforms/MacCatalyst/AppDelegate.cs
new file mode 100644
index 000000000..8fb3e5341
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Platforms/MacCatalyst/AppDelegate.cs
@@ -0,0 +1,9 @@
+using Foundation;
+
+namespace ShellRouteTemplates;
+
+[Register("AppDelegate")]
+public class AppDelegate : MauiUIApplicationDelegate
+{
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+}
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Platforms/MacCatalyst/Entitlements.plist b/11.0/Navigation/ShellRouteTemplates/src/Platforms/MacCatalyst/Entitlements.plist
new file mode 100644
index 000000000..772b296d4
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Platforms/MacCatalyst/Entitlements.plist
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ com.apple.security.app-sandbox
+
+
+ com.apple.security.network.client
+
+
+
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Platforms/MacCatalyst/Info.plist b/11.0/Navigation/ShellRouteTemplates/src/Platforms/MacCatalyst/Info.plist
new file mode 100644
index 000000000..f2e09873d
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Platforms/MacCatalyst/Info.plist
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UIDeviceFamily
+
+ 2
+
+ LSApplicationCategoryType
+ public.app-category.lifestyle
+ UIRequiredDeviceCapabilities
+
+ arm64
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ XSAppIconAssets
+ Assets.xcassets/appicon.appiconset
+
+
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Platforms/MacCatalyst/Program.cs b/11.0/Navigation/ShellRouteTemplates/src/Platforms/MacCatalyst/Program.cs
new file mode 100644
index 000000000..5880845aa
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Platforms/MacCatalyst/Program.cs
@@ -0,0 +1,15 @@
+using ObjCRuntime;
+using UIKit;
+
+namespace ShellRouteTemplates;
+
+public class Program
+{
+ // This is the main entry point of the application.
+ static void Main(string[] args)
+ {
+ // if you want to use a different Application Delegate class from "AppDelegate"
+ // you can specify it here.
+ UIApplication.Main(args, null, typeof(AppDelegate));
+ }
+}
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Platforms/Windows/App.xaml b/11.0/Navigation/ShellRouteTemplates/src/Platforms/Windows/App.xaml
new file mode 100644
index 000000000..442a28afb
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Platforms/Windows/App.xaml
@@ -0,0 +1,8 @@
+
+
+
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Platforms/Windows/App.xaml.cs b/11.0/Navigation/ShellRouteTemplates/src/Platforms/Windows/App.xaml.cs
new file mode 100644
index 000000000..6ac7e7597
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Platforms/Windows/App.xaml.cs
@@ -0,0 +1,23 @@
+using Microsoft.UI.Xaml;
+
+// To learn more about WinUI, the WinUI project structure,
+// and more about our project templates, see: http://aka.ms/winui-project-info.
+
+namespace ShellRouteTemplates.WinUI;
+
+///
+/// Provides application-specific behavior to supplement the default Application class.
+///
+public partial class App : MauiWinUIApplication
+{
+ ///
+ /// Initializes the singleton application object. This is the first line of authored code
+ /// executed, and as such is the logical equivalent of main() or WinMain().
+ ///
+ public App()
+ {
+ this.InitializeComponent();
+ }
+
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+}
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Platforms/Windows/Package.appxmanifest b/11.0/Navigation/ShellRouteTemplates/src/Platforms/Windows/Package.appxmanifest
new file mode 100644
index 000000000..c2b72fe0d
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Platforms/Windows/Package.appxmanifest
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+ $placeholder$
+ User Name
+ $placeholder$.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Platforms/Windows/app.manifest b/11.0/Navigation/ShellRouteTemplates/src/Platforms/Windows/app.manifest
new file mode 100644
index 000000000..13a0b8979
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Platforms/Windows/app.manifest
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+ true/PM
+ PerMonitorV2, PerMonitor
+
+ true
+
+
+
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Platforms/iOS/AppDelegate.cs b/11.0/Navigation/ShellRouteTemplates/src/Platforms/iOS/AppDelegate.cs
new file mode 100644
index 000000000..8fb3e5341
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Platforms/iOS/AppDelegate.cs
@@ -0,0 +1,9 @@
+using Foundation;
+
+namespace ShellRouteTemplates;
+
+[Register("AppDelegate")]
+public class AppDelegate : MauiUIApplicationDelegate
+{
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+}
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Platforms/iOS/Info.plist b/11.0/Navigation/ShellRouteTemplates/src/Platforms/iOS/Info.plist
new file mode 100644
index 000000000..0004a4fde
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Platforms/iOS/Info.plist
@@ -0,0 +1,32 @@
+
+
+
+
+ LSRequiresIPhoneOS
+
+ UIDeviceFamily
+
+ 1
+ 2
+
+ UIRequiredDeviceCapabilities
+
+ arm64
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ XSAppIconAssets
+ Assets.xcassets/appicon.appiconset
+
+
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Platforms/iOS/Program.cs b/11.0/Navigation/ShellRouteTemplates/src/Platforms/iOS/Program.cs
new file mode 100644
index 000000000..5880845aa
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Platforms/iOS/Program.cs
@@ -0,0 +1,15 @@
+using ObjCRuntime;
+using UIKit;
+
+namespace ShellRouteTemplates;
+
+public class Program
+{
+ // This is the main entry point of the application.
+ static void Main(string[] args)
+ {
+ // if you want to use a different Application Delegate class from "AppDelegate"
+ // you can specify it here.
+ UIApplication.Main(args, null, typeof(AppDelegate));
+ }
+}
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Platforms/iOS/Resources/PrivacyInfo.xcprivacy b/11.0/Navigation/ShellRouteTemplates/src/Platforms/iOS/Resources/PrivacyInfo.xcprivacy
new file mode 100644
index 000000000..24ab3b433
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Platforms/iOS/Resources/PrivacyInfo.xcprivacy
@@ -0,0 +1,51 @@
+
+
+
+
+
+ NSPrivacyAccessedAPITypes
+
+
+ NSPrivacyAccessedAPIType
+ NSPrivacyAccessedAPICategoryFileTimestamp
+ NSPrivacyAccessedAPITypeReasons
+
+ C617.1
+
+
+
+ NSPrivacyAccessedAPIType
+ NSPrivacyAccessedAPICategorySystemBootTime
+ NSPrivacyAccessedAPITypeReasons
+
+ 35F9.1
+
+
+
+ NSPrivacyAccessedAPIType
+ NSPrivacyAccessedAPICategoryDiskSpace
+ NSPrivacyAccessedAPITypeReasons
+
+ E174.1
+
+
+
+
+
+
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Properties/launchSettings.json b/11.0/Navigation/ShellRouteTemplates/src/Properties/launchSettings.json
new file mode 100644
index 000000000..de9182acd
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "Windows Machine": {
+ "commandName": "Project",
+ "nativeDebugging": false
+ }
+ }
+}
diff --git a/11.0/Navigation/ShellRouteTemplates/src/QueryPropertyResultPage.xaml b/11.0/Navigation/ShellRouteTemplates/src/QueryPropertyResultPage.xaml
new file mode 100644
index 000000000..eab1e1c10
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/QueryPropertyResultPage.xaml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/11.0/Navigation/ShellRouteTemplates/src/QueryPropertyResultPage.xaml.cs b/11.0/Navigation/ShellRouteTemplates/src/QueryPropertyResultPage.xaml.cs
new file mode 100644
index 000000000..fa2d33835
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/QueryPropertyResultPage.xaml.cs
@@ -0,0 +1,73 @@
+using ShellRouteTemplates.Models;
+
+namespace ShellRouteTemplates;
+
+[QueryProperty(nameof(TripId), "tripId")]
+[QueryProperty(nameof(CaseId), "caseId")]
+public partial class QueryPropertyResultPage : ContentPage
+{
+ string? caseId;
+ string? tripId;
+
+ protected QueryPropertyResultPage(string automationId)
+ {
+ InitializeComponent();
+ ActualLabel.AutomationId = $"ActualValue-{automationId}";
+ StatusLabel.AutomationId = $"ResultStatus-{automationId}";
+ }
+
+ public string? CaseId
+ {
+ get => caseId;
+ set
+ {
+ caseId = value;
+ Render();
+ }
+ }
+
+ public string? TripId
+ {
+ get => tripId;
+ set
+ {
+ tripId = value;
+ Render();
+ }
+ }
+
+ void Render()
+ {
+ if (caseId is null || tripId is null)
+ {
+ return;
+ }
+
+ RouteResultView.Render(
+ RouteCatalog.Find(caseId),
+ tripId,
+ FormLabel,
+ TemplateLabel,
+ DeliveryLabel,
+ ExpectedLabel,
+ ActualLabel,
+ StatusLabel);
+ }
+
+ async void OnBackToMatrix(object? sender, EventArgs e) =>
+ await Shell.Current.GoToAsync("//routes");
+}
+
+public sealed class RequiredResultPage : QueryPropertyResultPage
+{
+ public RequiredResultPage() : base("required")
+ {
+ }
+}
+
+public sealed class MixedResultPage : QueryPropertyResultPage
+{
+ public MixedResultPage() : base("mixed")
+ {
+ }
+}
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Resources/AppIcon/appicon.svg b/11.0/Navigation/ShellRouteTemplates/src/Resources/AppIcon/appicon.svg
new file mode 100644
index 000000000..456d12024
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Resources/AppIcon/appicon.svg
@@ -0,0 +1,4 @@
+
+
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Resources/AppIcon/appiconfg.svg b/11.0/Navigation/ShellRouteTemplates/src/Resources/AppIcon/appiconfg.svg
new file mode 100644
index 000000000..14f493237
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Resources/AppIcon/appiconfg.svg
@@ -0,0 +1,8 @@
+
+
+
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Resources/Fonts/OpenSans-Regular.ttf b/11.0/Navigation/ShellRouteTemplates/src/Resources/Fonts/OpenSans-Regular.ttf
new file mode 100644
index 000000000..846df940c
Binary files /dev/null and b/11.0/Navigation/ShellRouteTemplates/src/Resources/Fonts/OpenSans-Regular.ttf differ
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Resources/Fonts/OpenSans-Semibold.ttf b/11.0/Navigation/ShellRouteTemplates/src/Resources/Fonts/OpenSans-Semibold.ttf
new file mode 100644
index 000000000..d655185e9
Binary files /dev/null and b/11.0/Navigation/ShellRouteTemplates/src/Resources/Fonts/OpenSans-Semibold.ttf differ
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Resources/Images/dotnet_bot.png b/11.0/Navigation/ShellRouteTemplates/src/Resources/Images/dotnet_bot.png
new file mode 100644
index 000000000..054167e59
Binary files /dev/null and b/11.0/Navigation/ShellRouteTemplates/src/Resources/Images/dotnet_bot.png differ
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Resources/Raw/AboutAssets.txt b/11.0/Navigation/ShellRouteTemplates/src/Resources/Raw/AboutAssets.txt
new file mode 100644
index 000000000..89dc758d6
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Resources/Raw/AboutAssets.txt
@@ -0,0 +1,15 @@
+Any raw assets you want to be deployed with your application can be placed in
+this directory (and child directories). Deployment of the asset to your application
+is automatically handled by the following `MauiAsset` Build Action within your `.csproj`.
+
+
+
+These files will be deployed with your package and will be accessible using Essentials:
+
+ async Task LoadMauiAsset()
+ {
+ using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt");
+ using var reader = new StreamReader(stream);
+
+ var contents = reader.ReadToEnd();
+ }
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Resources/Splash/splash.svg b/11.0/Navigation/ShellRouteTemplates/src/Resources/Splash/splash.svg
new file mode 100644
index 000000000..14f493237
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Resources/Splash/splash.svg
@@ -0,0 +1,8 @@
+
+
+
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Resources/Styles/Colors.xaml b/11.0/Navigation/ShellRouteTemplates/src/Resources/Styles/Colors.xaml
new file mode 100644
index 000000000..d7a6aafd9
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Resources/Styles/Colors.xaml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+ #512BD4
+ #ac99ea
+ #242424
+ #DFD8F7
+ #9880e5
+ #2B0B98
+
+ White
+ Black
+ #D600AA
+ #190649
+ #1f1f1f
+
+ #E1E1E1
+ #C8C8C8
+ #ACACAC
+ #919191
+ #6E6E6E
+ #404040
+ #212121
+ #141414
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/11.0/Navigation/ShellRouteTemplates/src/Resources/Styles/Styles.xaml b/11.0/Navigation/ShellRouteTemplates/src/Resources/Styles/Styles.xaml
new file mode 100644
index 000000000..af1909d8d
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/Resources/Styles/Styles.xaml
@@ -0,0 +1,414 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/11.0/Navigation/ShellRouteTemplates/src/RouteResultView.cs b/11.0/Navigation/ShellRouteTemplates/src/RouteResultView.cs
new file mode 100644
index 000000000..c7dc5d56d
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/RouteResultView.cs
@@ -0,0 +1,37 @@
+using ShellRouteTemplates.Models;
+
+namespace ShellRouteTemplates;
+
+internal static class RouteResultView
+{
+ public static void Render(
+ RouteExample? example,
+ string? actualValue,
+ Label formLabel,
+ Label templateLabel,
+ Label deliveryLabel,
+ Label expectedLabel,
+ Label actualLabel,
+ Label statusLabel)
+ {
+ if (example is null)
+ {
+ statusLabel.Text = "FAIL: route case metadata was not delivered";
+ statusLabel.TextColor = Colors.Red;
+ return;
+ }
+
+ var normalizedActual = string.IsNullOrEmpty(actualValue)
+ ? RouteCatalog.NotSupplied
+ : actualValue;
+ var passed = normalizedActual == example.ExpectedValue;
+
+ formLabel.Text = example.Form;
+ templateLabel.Text = example.Template;
+ deliveryLabel.Text = $"{example.Delivery}: {example.ParameterName}";
+ expectedLabel.Text = example.ExpectedValue;
+ actualLabel.Text = normalizedActual;
+ statusLabel.Text = passed ? "PASS" : "FAIL";
+ statusLabel.TextColor = passed ? Colors.Green : Colors.Red;
+ }
+}
diff --git a/11.0/Navigation/ShellRouteTemplates/src/ShellRouteTemplates.csproj b/11.0/Navigation/ShellRouteTemplates/src/ShellRouteTemplates.csproj
new file mode 100644
index 000000000..0ccbaa7cc
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/ShellRouteTemplates.csproj
@@ -0,0 +1,66 @@
+
+
+
+ net11.0-android;net11.0-ios;net11.0-maccatalyst
+ $(TargetFrameworks);net11.0-windows10.0.19041.0
+
+
+
+
+ Exe
+ ShellRouteTemplates
+ true
+ true
+ enable
+ enable
+
+
+
+ Shell Route Templates
+
+
+ com.companyname.shellroutetemplates
+
+
+ 1.0
+ 1
+
+
+ None
+
+ 15.0
+ 17.0
+ 24.0
+ 10.0.17763.0
+ 10.0.17763.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/11.0/Navigation/ShellRouteTemplates/src/ShellRouteTemplates.sln b/11.0/Navigation/ShellRouteTemplates/src/ShellRouteTemplates.sln
new file mode 100644
index 000000000..1469e0fae
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/ShellRouteTemplates.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31903.59
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShellRouteTemplates", "ShellRouteTemplates.csproj", "{C76F00A3-4632-47B4-80FA-08EC392AD584}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C76F00A3-4632-47B4-80FA-08EC392AD584}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C76F00A3-4632-47B4-80FA-08EC392AD584}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C76F00A3-4632-47B4-80FA-08EC392AD584}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {C76F00A3-4632-47B4-80FA-08EC392AD584}.Debug|x64.Build.0 = Debug|Any CPU
+ {C76F00A3-4632-47B4-80FA-08EC392AD584}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {C76F00A3-4632-47B4-80FA-08EC392AD584}.Debug|x86.Build.0 = Debug|Any CPU
+ {C76F00A3-4632-47B4-80FA-08EC392AD584}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C76F00A3-4632-47B4-80FA-08EC392AD584}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C76F00A3-4632-47B4-80FA-08EC392AD584}.Release|x64.ActiveCfg = Release|Any CPU
+ {C76F00A3-4632-47B4-80FA-08EC392AD584}.Release|x64.Build.0 = Release|Any CPU
+ {C76F00A3-4632-47B4-80FA-08EC392AD584}.Release|x86.ActiveCfg = Release|Any CPU
+ {C76F00A3-4632-47B4-80FA-08EC392AD584}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/11.0/Navigation/ShellRouteTemplates/src/ViewModels/MainPageViewModel.cs b/11.0/Navigation/ShellRouteTemplates/src/ViewModels/MainPageViewModel.cs
new file mode 100644
index 000000000..099586d0e
--- /dev/null
+++ b/11.0/Navigation/ShellRouteTemplates/src/ViewModels/MainPageViewModel.cs
@@ -0,0 +1,13 @@
+using CommunityToolkit.Mvvm.Input;
+using ShellRouteTemplates.Models;
+
+namespace ShellRouteTemplates.ViewModels;
+
+public partial class MainPageViewModel
+{
+ public IReadOnlyList Examples => RouteCatalog.Examples;
+
+ [RelayCommand]
+ private static Task NavigateAsync(RouteExample example) =>
+ Shell.Current.GoToAsync(example.NavigationUri);
+}