diff --git a/samples/ControlGallery/Models/NavigationParameterModel.cs b/samples/ControlGallery/Models/NavigationParameterModel.cs new file mode 100644 index 00000000..0e014530 --- /dev/null +++ b/samples/ControlGallery/Models/NavigationParameterModel.cs @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace ControlGallery.Models +{ + public class NavigationParameterModel + { + public string Name { get; set; } + public string Value { get; set; } + } +} diff --git a/samples/ControlGallery/Views/NavigationSource.razor b/samples/ControlGallery/Views/NavigationSource.razor index 411eb1d1..b5e67477 100644 --- a/samples/ControlGallery/Views/NavigationSource.razor +++ b/samples/ControlGallery/Views/NavigationSource.razor @@ -1,4 +1,5 @@ @page "/navigation" +@using ControlGallery.Models @inject ShellNavigationManager NavigationManager @@ -15,6 +16,7 @@ + @@ -32,4 +34,10 @@ async Task NavigateWithGuid() => await NavigationManager.NavigateToAsync($"/guid/{Guid.NewGuid()}"); async Task NavigateWithNullableGuid() => await NavigationManager.NavigateToAsync($"/nullable-guid/{Guid.NewGuid()}"); async Task NavigateWithBool() => await NavigationManager.NavigateToAsync("/bool/true"); + + async Task NavigateWithAdditionalParameters() => await NavigationManager.NavigateToAsync("/target", new Dictionary + { + ["Query1"] = new NavigationParameterModel { Name = "Q1", Value = "V1" }, + ["Query2"] = new NavigationParameterModel { Name = "Q2", Value = null } + }); } diff --git a/samples/ControlGallery/Views/NavigationTarget.razor b/samples/ControlGallery/Views/NavigationTarget.razor index efc0bcd7..5cc15214 100644 --- a/samples/ControlGallery/Views/NavigationTarget.razor +++ b/samples/ControlGallery/Views/NavigationTarget.razor @@ -9,6 +9,7 @@ @page "/guid/{Guid}" @page "/nullable-guid/{NullableGuid}" @page "/bool/{Bool}" +@using ControlGallery.Models @@ -26,6 +27,8 @@ + + @@ -41,6 +44,6 @@ [Parameter] public Guid Guid { get; set; } [Parameter] public Guid? NullableGuid { get; set; } [Parameter] public bool Bool { get; set; } - - + [Parameter] public NavigationParameterModel Query1 { get; set; } + [Parameter] public NavigationParameterModel Query2 { get; set; } } diff --git a/src/BlazorBindings.Maui/ShellNavigation/MBBRouteFactory.cs b/src/BlazorBindings.Maui/ShellNavigation/MBBRouteFactory.cs index e81069af..8018e1fc 100644 --- a/src/BlazorBindings.Maui/ShellNavigation/MBBRouteFactory.cs +++ b/src/BlazorBindings.Maui/ShellNavigation/MBBRouteFactory.cs @@ -8,7 +8,7 @@ namespace BlazorBindings.Maui.ShellNavigation { //Based on the forms TypeRouteFactory https://github.com/xamarin/Xamarin.Forms/blob/9fd882e6c598a51bffbbb2f4de72c3bd9023ab41/Xamarin.Forms.Core/Routing.cs - public class MBBRouteFactory : MC.RouteFactory + internal class MBBRouteFactory : MC.RouteFactory { private readonly Type _componentType; private readonly ShellNavigationManager _navigationManager; diff --git a/src/BlazorBindings.Maui/ShellNavigation/ShellNavigationManager.cs b/src/BlazorBindings.Maui/ShellNavigation/ShellNavigationManager.cs index 10c5e90f..44a9d469 100644 --- a/src/BlazorBindings.Maui/ShellNavigation/ShellNavigationManager.cs +++ b/src/BlazorBindings.Maui/ShellNavigation/ShellNavigationManager.cs @@ -65,14 +65,14 @@ private void FindRoutes() } #pragma warning disable CA1054 // Uri parameters should not be strings - public void NavigateTo(string uri) + public void NavigateTo(string uri, Dictionary parameters = null) #pragma warning restore CA1054 // Uri parameters should not be strings { - _ = NavigateToAsync(uri); + _ = NavigateToAsync(uri, parameters); } #pragma warning disable CA1054 // Uri parameters should not be strings - public async Task NavigateToAsync(string uri) + public async Task NavigateToAsync(string uri, Dictionary parameters = null) #pragma warning restore CA1054 // Uri parameters should not be strings { if (uri is null) @@ -80,7 +80,7 @@ public async Task NavigateToAsync(string uri) throw new ArgumentNullException(nameof(uri)); } - var route = StructuredRoute.FindBestMatch(uri, Routes); + var route = StructuredRoute.FindBestMatch(uri, Routes, parameters); if (route != null) { @@ -110,8 +110,24 @@ public async Task NavigateToAsync(string uri) var renderer = serviceProvider.GetRequiredService(); - var convertedParameters = ConvertParameters(componentType, route.Parameters); - var addComponentTask = renderer.AddComponent(componentType, container, convertedParameters); + var parameters = ConvertParameters(componentType, route.PathParameters); + + if (route.AdditionalParameters is not null) + { + if (parameters is null) + { + parameters = route.AdditionalParameters; + } + else + { + foreach (var (key, value) in route.AdditionalParameters) + { + parameters.Add(key, value); + } + } + } + + var addComponentTask = renderer.AddComponent(componentType, container, parameters); var elementAddedTask = container.WaitForElementAsync(); await Task.WhenAny(addComponentTask, elementAddedTask).ConfigureAwait(false); diff --git a/src/BlazorBindings.Maui/ShellNavigation/StructuredRoute.cs b/src/BlazorBindings.Maui/ShellNavigation/StructuredRoute.cs index 459cddd0..c146b3d8 100644 --- a/src/BlazorBindings.Maui/ShellNavigation/StructuredRoute.cs +++ b/src/BlazorBindings.Maui/ShellNavigation/StructuredRoute.cs @@ -8,7 +8,7 @@ namespace BlazorBindings.Maui.ShellNavigation { //Used to map blazor route syntax to forms query syntax - public class StructuredRoute + internal class StructuredRoute { #pragma warning disable CA1056 // Uri properties should not be strings public string OriginalUri { get; }//Full route as it is registered in the razor component @@ -41,12 +41,12 @@ public StructuredRoute(string originalRoute, Type type) } } - internal static StructuredRouteResult FindBestMatch(string uri, List routes) + internal static StructuredRouteResult FindBestMatch(string uri, List routes, Dictionary additionalParameters) { var match = routes.FirstOrDefault(x => x.BaseUri == uri); if (match != null && match.ParameterCount == 0) { - return new StructuredRouteResult(match); + return new StructuredRouteResult(match, additionalParameters: additionalParameters); } var pieces = uri.Split('/').ToList(); @@ -71,27 +71,31 @@ internal static StructuredRouteResult FindBestMatch(string uri, List Parameters { get; } = new Dictionary(); + public Dictionary PathParameters { get; } = new Dictionary(); + public Dictionary AdditionalParameters { get; } - public StructuredRouteResult(StructuredRoute match) - { - Route = match; - } - - public StructuredRouteResult(StructuredRoute match, List parameters) + public StructuredRouteResult(StructuredRoute match, + List parameters = null, + Dictionary additionalParameters = null) { Route = match ?? throw new ArgumentNullException(nameof(match)); - for (var i = 0; i < match.ParameterKeys.Count; i++) + + if (parameters is not null) { - Parameters[match.ParameterKeys[i]] = parameters.ElementAtOrDefault(i); + for (var i = 0; i < match.ParameterKeys.Count; i++) + { + PathParameters[match.ParameterKeys[i]] = parameters.ElementAtOrDefault(i); + } } + + AdditionalParameters = additionalParameters; } } }