From 5e0aec3ac45499827e59ced87485676831a22621 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Thu, 29 Jun 2023 19:14:42 -0500 Subject: [PATCH 1/7] Add API for temporary nav parameter --- src/Controls/src/Core/Shell/Shell.cs | 25 +++++ src/Controls/src/Core/Shell/ShellContent.cs | 13 +++ .../src/Core/Shell/ShellNavigationManager.cs | 33 +------ .../src/Core/Shell/ShellRouteParameters.cs | 70 +++++++++++-- .../ShellParameterPassingTests.cs | 98 +++++++++++++++++++ .../tests/Core.UnitTests/ShellTestBase.cs | 8 +- 6 files changed, 207 insertions(+), 40 deletions(-) diff --git a/src/Controls/src/Core/Shell/Shell.cs b/src/Controls/src/Core/Shell/Shell.cs index 179de869928a..138fff8b5d1f 100644 --- a/src/Controls/src/Core/Shell/Shell.cs +++ b/src/Controls/src/Core/Shell/Shell.cs @@ -691,6 +691,31 @@ public Task GoToAsync(ShellNavigationState state, bool animate, IDictionary + /// + /// + /// + /// Any parameters passed here won't be reused when the page is navigated back to + /// + public Task GoToAsync(ShellNavigationState state, KeyValuePair singleUseQueryParameter) + { + return _navigationManager.GoToAsync(state, null, false, parameters: new ShellRouteParameters(singleUseQueryParameter)); + } + + /// + /// + /// + /// + /// + /// Any parameters passed here won't be reused when the page is navigated back to + /// + public Task GoToAsync(ShellNavigationState state, bool animate, KeyValuePair singleUseQueryParameter) + { + return _navigationManager.GoToAsync(state, animate, false, parameters: new ShellRouteParameters(singleUseQueryParameter)); + } +#pragma warning restore RS0016 // Add public types and members to the declared API + public void AddLogicalChild(Element element) { if (element == null) diff --git a/src/Controls/src/Core/Shell/ShellContent.cs b/src/Controls/src/Core/Shell/ShellContent.cs index 9c3a465a682a..712bda517d02 100644 --- a/src/Controls/src/Core/Shell/ShellContent.cs +++ b/src/Controls/src/Core/Shell/ShellContent.cs @@ -295,7 +295,10 @@ static void ApplyQueryAttributes(object content, ShellRouteParameters query, She var type = content.GetType(); var queryPropertyAttributes = type.GetCustomAttributes(typeof(QueryPropertyAttribute), true); if (queryPropertyAttributes.Length == 0) + { + ClearQueryIfAppliedToPage(query, content); return; + } foreach (QueryPropertyAttribute attrib in queryPropertyAttributes) { @@ -327,6 +330,16 @@ static void ApplyQueryAttributes(object content, ShellRouteParameters query, She prop.SetValue(content, null); } } + + ClearQueryIfAppliedToPage(query, content); + + static void ClearQueryIfAppliedToPage(ShellRouteParameters query, object content) + { + // Once we've applied the attributes to ContentPage lets remove the + // parameters used during navigation + if (content is ContentPage) + query.ResetToQueryParameters(); + } } } } diff --git a/src/Controls/src/Core/Shell/ShellNavigationManager.cs b/src/Controls/src/Core/Shell/ShellNavigationManager.cs index 986684000caa..9329bf1a5f11 100644 --- a/src/Controls/src/Core/Shell/ShellNavigationManager.cs +++ b/src/Controls/src/Core/Shell/ShellNavigationManager.cs @@ -92,8 +92,7 @@ internal async Task GoToAsync( var uri = navigationRequest.Request.FullUri; var queryString = navigationRequest.Query; - var queryData = ParseQueryString(queryString); - parameters.Merge(queryData); + parameters.SetQueryStringParameters(queryString); ApplyQueryAttributes(_shell, parameters, false, false); var shellItem = navigationRequest.Request.Item; @@ -306,17 +305,7 @@ public static void ApplyQueryAttributes(Element element, ShellRouteParameters qu baseShellItem = element?.Parent as BaseShellItem; //filter the query to only apply the keys with matching prefix - var filteredQuery = new ShellRouteParameters(query.Count); - - foreach (var q in query) - { - if (!q.Key.StartsWith(prefix, StringComparison.Ordinal)) - continue; - var key = q.Key.Substring(prefix.Length); - if (key.IndexOf(".", StringComparison.Ordinal) != -1) - continue; - filteredQuery.Add(key, q.Value); - } + var filteredQuery = new ShellRouteParameters(query, prefix); if (baseShellItem is ShellContent) @@ -488,24 +477,6 @@ public static ShellNavigationSource CalculateNavigationSource(Shell shell, Shell return ShellNavigationSource.Push; } - static Dictionary ParseQueryString(string query) - { - if (query.StartsWith("?", StringComparison.Ordinal)) - query = query.Substring(1); - Dictionary lookupDict = new(StringComparer.Ordinal); - if (query == null) - return lookupDict; - foreach (var part in query.Split('&')) - { - var p = part.Split('='); - if (p.Length != 2) - continue; - lookupDict[p[0]] = p[1]; - } - - return lookupDict; - } - public static ShellNavigationParameters GetNavigationParameters( ShellItem shellItem, ShellSection shellSection, diff --git a/src/Controls/src/Core/Shell/ShellRouteParameters.cs b/src/Controls/src/Core/Shell/ShellRouteParameters.cs index 5b67497fc2a8..461dde3a7199 100644 --- a/src/Controls/src/Core/Shell/ShellRouteParameters.cs +++ b/src/Controls/src/Core/Shell/ShellRouteParameters.cs @@ -1,5 +1,6 @@ #nullable disable using System; +using System.Collections; using System.Collections.Generic; using System.Text; @@ -7,33 +8,86 @@ namespace Microsoft.Maui.Controls { internal class ShellRouteParameters : Dictionary { + KeyValuePair? _singleUseQueryParameter; + public ShellRouteParameters() { } public ShellRouteParameters(ShellRouteParameters shellRouteParams) : base(shellRouteParams) { + _singleUseQueryParameter = shellRouteParams._singleUseQueryParameter; + } + + internal ShellRouteParameters(ShellRouteParameters query, string prefix) + : base(query.Count) + { + foreach (var q in query) + { + if (!q.Key.StartsWith(prefix, StringComparison.Ordinal)) + continue; + var key = q.Key.Substring(prefix.Length); + if (key.IndexOf(".", StringComparison.Ordinal) != -1) + continue; + this.Add(key, q.Value); + } + + _singleUseQueryParameter = query._singleUseQueryParameter; } - public ShellRouteParameters(IDictionary shellRouteParams) : base(shellRouteParams) + internal ShellRouteParameters(IDictionary shellRouteParams) : base(shellRouteParams) { } - public ShellRouteParameters(int count) - : base(count) + internal ShellRouteParameters(KeyValuePair singleUseQueryParameter) { + this.Add(singleUseQueryParameter.Key, singleUseQueryParameter.Value); + _singleUseQueryParameter = singleUseQueryParameter; } - internal void Merge(IDictionary input) + internal void ResetToQueryParameters() { - if (input == null || input.Count == 0) + if (_singleUseQueryParameter is null) return; - foreach (var item in input) - Add(item.Key, item.Value); + if (this.ContainsKey(_singleUseQueryParameter.Value.Key)) + { + this.Remove(_singleUseQueryParameter.Value.Key); + _singleUseQueryParameter = null; + } } - } + internal void SetQueryStringParameters(string query) + { + var queryStringParameters = ParseQueryString(query); + if (queryStringParameters == null || queryStringParameters.Count == 0) + return; + + foreach (var item in queryStringParameters) + { + if (!this.ContainsKey(item.Key)) + this[item.Key] = item.Value; + } + } + + static Dictionary ParseQueryString(string query) + { + if (query.StartsWith("?", StringComparison.Ordinal)) + query = query.Substring(1); + Dictionary lookupDict = new(StringComparer.Ordinal); + if (query == null) + return lookupDict; + foreach (var part in query.Split('&')) + { + var p = part.Split('='); + if (p.Length != 2) + continue; + lookupDict[p[0]] = p[1]; + } + + return lookupDict; + } + } internal static class ShellParameterExtensions { diff --git a/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs b/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs index 73978e3b78c8..cd56f0515638 100644 --- a/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs +++ b/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Xunit; @@ -376,6 +377,103 @@ public async Task BasicShellParameterTest() Assert.Equal(obj, testPage.ComplexObject); } + [Fact] + public async Task ExtraParametersDontGetRetained() + { + var shell = new Shell(); + var item = CreateShellItem(shellSectionRoute: "section2"); + Routing.RegisterRoute("details", typeof(ShellTestPage)); + shell.Items.Add(item); + var obj = new object(); + var parameter = new ShellRouteParameters + { + {"DoubleQueryParameter", 2d }, + { "ComplexObject", obj} + }; + + await shell.GoToAsync(new ShellNavigationState($"details?{nameof(ShellTestPage.SomeQueryParameter)}=1234"), parameter); + var testPage = (shell.CurrentItem.CurrentItem as IShellSectionController).PresentedPage as ShellTestPage; + + await shell.Navigation.PushAsync(new ContentPage()); + + testPage.SomeQueryParameter = String.Empty; + testPage.DoubleQueryParameter = -1d; + testPage.ComplexObject = null; + + await shell.GoToAsync(".."); + + Assert.Equal("1234", testPage.SomeQueryParameter); + Assert.Equal(-1d, testPage.DoubleQueryParameter); + Assert.Null(testPage.ComplexObject); + + // ensure that AppliedQueryAttributes is called with correct parameters each time + Assert.Equal(2, testPage.AppliedQueryAttributes.Count); + Assert.Equal(3, testPage.AppliedQueryAttributes[0].Count); + Assert.Equal(1, testPage.AppliedQueryAttributes[1].Count); + Assert.Equal($"{nameof(ShellTestPage.SomeQueryParameter)}", testPage.AppliedQueryAttributes[1].Keys.First()); + } + + [Fact] + public async Task ExtraParametersArentReAppliedWhenNavigatingBackToShellContent() + { + var shell = new Shell(); + var item = CreateShellItem(shellContentRoute: "start"); + var withParams = CreateShellItem(page: new ShellTestPage(), shellContentRoute: "withParams", templated: true); + shell.Items.Add(item); + shell.Items.Add(withParams); + var obj = new object(); + var parameter = new ShellRouteParameters + { + { "ComplexObject", obj}, + { nameof(ShellTestPage.SomeQueryParameter), "1234"} + }; + + await shell.GoToAsync(new ShellNavigationState($"//start")); + await shell.GoToAsync(new ShellNavigationState($"//withParams"), parameter); + + var testPage = (shell.CurrentItem.CurrentItem.CurrentItem as IShellContentController).GetOrCreateContent() as ShellTestPage; + + // Validate parameter was set during first navigation + Assert.Equal(obj, testPage.ComplexObject); + + // Clear parameters + testPage.ComplexObject = null; + testPage.SomeQueryParameter = null; + + // Navigate away and back to page with params + await shell.GoToAsync(new ShellNavigationState($"//start")); + shell.CurrentItem = withParams; + await Task.Yield(); + + var testPage2 = (shell.CurrentItem.CurrentItem as IShellSectionController).PresentedPage as ShellTestPage; + Assert.Null(testPage2.SomeQueryParameter); + Assert.Null(testPage2.ComplexObject); + Assert.Equal(testPage2, testPage); + } + + [Fact] + public async Task SingleUseQueryParametersReplaceQueryStringParams() + { + var shell = new Shell(); + var item = CreateShellItem(shellSectionRoute: "section2"); + Routing.RegisterRoute("details", typeof(ShellTestPage)); + shell.Items.Add(item); + + var parameter = new KeyValuePair( + $"{nameof(ShellTestPage.SomeQueryParameter)}", "4321"); + + await shell.GoToAsync(new ShellNavigationState($"details?{nameof(ShellTestPage.SomeQueryParameter)}=1234"), parameter); + var testPage = (shell.CurrentItem.CurrentItem as IShellSectionController).PresentedPage as ShellTestPage; + + // Parameters passed in will win + Assert.Equal("4321", testPage.SomeQueryParameter); + await shell.Navigation.PushAsync(new ContentPage()); + testPage.SomeQueryParameter = "TheseDontGetSetAgain"; + await shell.GoToAsync(".."); + + Assert.Equal("TheseDontGetSetAgain", testPage.SomeQueryParameter); + } + [Fact] public async Task DotDotNavigationPassesShellParameters() { diff --git a/src/Controls/tests/Core.UnitTests/ShellTestBase.cs b/src/Controls/tests/Core.UnitTests/ShellTestBase.cs index a21c6d557ce4..2bbcfdfe8047 100644 --- a/src/Controls/tests/Core.UnitTests/ShellTestBase.cs +++ b/src/Controls/tests/Core.UnitTests/ShellTestBase.cs @@ -88,7 +88,7 @@ protected ShellSection MakeSimpleShellSection(string route, string contentRoute, [QueryProperty("SomeQueryParameter", "SomeQueryParameter")] [QueryProperty("CancelNavigationOnBackButtonPressed", "CancelNavigationOnBackButtonPressed")] [QueryProperty("ComplexObject", "ComplexObject")] - public class ShellTestPage : ContentPage + public class ShellTestPage : ContentPage, IQueryAttributable { public string CancelNavigationOnBackButtonPressed { get; set; } public ShellTestPage() @@ -128,6 +128,12 @@ protected override bool OnBackButtonPressed() return base.OnBackButtonPressed(); } + + public List> AppliedQueryAttributes = new List>(); + public void ApplyQueryAttributes(IDictionary query) + { + AppliedQueryAttributes.Add(new Dictionary(query)); + } } protected ShellItem CreateShellItem( From 82af5c9f8a9bb5e8bdd5a30cd023cd02dcae1f4b Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Thu, 29 Jun 2023 21:29:42 -0500 Subject: [PATCH 2/7] - update to collection --- src/Controls/src/Core/Shell/Shell.cs | 4 +- .../Shell/ShellNavigationQueryParameters.cs | 94 +++++++++++++++++++ .../src/Core/Shell/ShellRouteParameters.cs | 26 +++-- .../ShellParameterPassingTests.cs | 22 +++-- 4 files changed, 124 insertions(+), 22 deletions(-) create mode 100644 src/Controls/src/Core/Shell/ShellNavigationQueryParameters.cs diff --git a/src/Controls/src/Core/Shell/Shell.cs b/src/Controls/src/Core/Shell/Shell.cs index 138fff8b5d1f..7c2c747a4f85 100644 --- a/src/Controls/src/Core/Shell/Shell.cs +++ b/src/Controls/src/Core/Shell/Shell.cs @@ -698,7 +698,7 @@ public Task GoToAsync(ShellNavigationState state, bool animate, IDictionary /// Any parameters passed here won't be reused when the page is navigated back to /// - public Task GoToAsync(ShellNavigationState state, KeyValuePair singleUseQueryParameter) + public Task GoToAsync(ShellNavigationState state, ShellNavigationQueryParameters singleUseQueryParameter) { return _navigationManager.GoToAsync(state, null, false, parameters: new ShellRouteParameters(singleUseQueryParameter)); } @@ -710,7 +710,7 @@ public Task GoToAsync(ShellNavigationState state, KeyValuePair s /// /// Any parameters passed here won't be reused when the page is navigated back to /// - public Task GoToAsync(ShellNavigationState state, bool animate, KeyValuePair singleUseQueryParameter) + public Task GoToAsync(ShellNavigationState state, bool animate, ShellNavigationQueryParameters singleUseQueryParameter) { return _navigationManager.GoToAsync(state, animate, false, parameters: new ShellRouteParameters(singleUseQueryParameter)); } diff --git a/src/Controls/src/Core/Shell/ShellNavigationQueryParameters.cs b/src/Controls/src/Core/Shell/ShellNavigationQueryParameters.cs new file mode 100644 index 000000000000..7b0e3f13b0b5 --- /dev/null +++ b/src/Controls/src/Core/Shell/ShellNavigationQueryParameters.cs @@ -0,0 +1,94 @@ +#nullable disable +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace Microsoft.Maui.Controls +{ +#pragma warning disable RS0016 // Add public types and members to the declared API + public class ShellNavigationQueryParameters : IDictionary + { + Dictionary _internal = new Dictionary(); + bool _isReadonly; + + public ShellNavigationQueryParameters() + { + } + + public ShellNavigationQueryParameters(IEnumerable> collection) + { + foreach (var item in collection) + this.Add(item.Key, item.Value); + } + + public ShellNavigationQueryParameters(IDictionary dictionary) + { + foreach (var item in dictionary) + this.Add(item.Key, item.Value); + } + + internal void SetToReadOnly() => + _isReadonly = true; + + void CheckReadOnlyState() + { + if (_isReadonly) + throw new InvalidOperationException($"ShellNavigationQueryParameters are ReadOnly"); + } + + public object this[string key] + { + get => _internal[key]; + set + { + CheckReadOnlyState(); + _internal[key] = value; + } + } + + public ICollection Keys => _internal.Keys; + + public ICollection Values => _internal.Values; + + public int Count => _internal.Count; + + public bool IsReadOnly => _isReadonly; + + public void Add(string key, object value) => _internal.Add(key, value); + + public void Add(KeyValuePair item) => _internal.Add(item.Key, item.Value); + + public void Clear() => _internal.Clear(); + + public bool Contains(KeyValuePair item) => _internal.ContainsKey(item.Key); + + public bool ContainsKey(string key) => _internal.ContainsKey(key); + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + => (_internal as ICollection>)?.CopyTo(array, arrayIndex); + + public IEnumerator> GetEnumerator() => _internal.GetEnumerator(); + + public bool Remove(string key) + { + CheckReadOnlyState(); + return _internal.Remove(key); + } + + public bool Remove(KeyValuePair item) + { + CheckReadOnlyState(); + return (_internal as ICollection>).Remove(item); + } + + public bool TryGetValue(string key, out object value) + { + return _internal.TryGetValue(key, out value); + } + + IEnumerator IEnumerable.GetEnumerator() => + _internal.GetEnumerator(); + } +#pragma warning restore RS0016 // Add public types and members to the declared API +} \ No newline at end of file diff --git a/src/Controls/src/Core/Shell/ShellRouteParameters.cs b/src/Controls/src/Core/Shell/ShellRouteParameters.cs index 461dde3a7199..29bdee2459eb 100644 --- a/src/Controls/src/Core/Shell/ShellRouteParameters.cs +++ b/src/Controls/src/Core/Shell/ShellRouteParameters.cs @@ -8,7 +8,7 @@ namespace Microsoft.Maui.Controls { internal class ShellRouteParameters : Dictionary { - KeyValuePair? _singleUseQueryParameter; + ShellNavigationQueryParameters _singleUseQueryParameters; public ShellRouteParameters() { @@ -16,7 +16,7 @@ public ShellRouteParameters() public ShellRouteParameters(ShellRouteParameters shellRouteParams) : base(shellRouteParams) { - _singleUseQueryParameter = shellRouteParams._singleUseQueryParameter; + _singleUseQueryParameters = shellRouteParams._singleUseQueryParameters; } internal ShellRouteParameters(ShellRouteParameters query, string prefix) @@ -32,29 +32,35 @@ internal ShellRouteParameters(ShellRouteParameters query, string prefix) this.Add(key, q.Value); } - _singleUseQueryParameter = query._singleUseQueryParameter; + _singleUseQueryParameters = query._singleUseQueryParameters; } internal ShellRouteParameters(IDictionary shellRouteParams) : base(shellRouteParams) { } - internal ShellRouteParameters(KeyValuePair singleUseQueryParameter) + internal ShellRouteParameters(ShellNavigationQueryParameters singleUseQueryParameters) { - this.Add(singleUseQueryParameter.Key, singleUseQueryParameter.Value); - _singleUseQueryParameter = singleUseQueryParameter; + foreach (var item in singleUseQueryParameters) + this.Add(item.Key, item.Value); + + _singleUseQueryParameters = singleUseQueryParameters; } internal void ResetToQueryParameters() { - if (_singleUseQueryParameter is null) + if (_singleUseQueryParameters is null) return; - if (this.ContainsKey(_singleUseQueryParameter.Value.Key)) + foreach (var item in _singleUseQueryParameters) { - this.Remove(_singleUseQueryParameter.Value.Key); - _singleUseQueryParameter = null; + if (this.ContainsKey(item.Key)) + { + this.Remove(item.Key); + } } + + _singleUseQueryParameters = null; } internal void SetQueryStringParameters(string query) diff --git a/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs b/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs index cd56f0515638..8f34a24a5219 100644 --- a/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs +++ b/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs @@ -151,7 +151,7 @@ public async Task NavigationBetweenShellContentsPassesQueryString() await shell.GoToAsync(new ShellNavigationState($"//content?{nameof(ShellTestPage.SomeQueryParameter)}=1234")); await shell.GoToAsync(new ShellNavigationState($"//section2/details?{nameof(ShellTestPage.SomeQueryParameter)}=4321")); - var testPage = (shell.CurrentItem.CurrentItem as IShellSectionController).PresentedPage as ShellTestPage; + var testPage = shell.CurrentPage as ShellTestPage; Assert.Equal("4321", testPage.SomeQueryParameter); } @@ -201,7 +201,7 @@ public async Task NavigationBetweenFlyoutItemWithPushedPageRetainsQueryString() await shellController.OnFlyoutItemSelectedAsync(flyoutItem1); await shellController.OnFlyoutItemSelectedAsync(flyoutItem2); - var testPage = (shell.CurrentItem.CurrentItem as IShellSectionController).PresentedPage as ShellTestPage; + var testPage = shell.CurrentPage as ShellTestPage; Assert.Equal("1234", testPage.SomeQueryParameter); } @@ -214,7 +214,7 @@ public async Task BasicQueryStringTest() Routing.RegisterRoute("details", typeof(ShellTestPage)); shell.Items.Add(item); await shell.GoToAsync(new ShellNavigationState($"details?{nameof(ShellTestPage.SomeQueryParameter)}=1234")); - var testPage = (shell.CurrentItem.CurrentItem as IShellSectionController).PresentedPage as ShellTestPage; + var testPage = shell.CurrentPage as ShellTestPage; Assert.Equal("1234", testPage.SomeQueryParameter); } @@ -291,7 +291,7 @@ public async Task SetParameterOfTypeThatsNotAString() Routing.RegisterRoute("details", typeof(ShellTestPage)); shell.Items.Add(item); await shell.GoToAsync(new ShellNavigationState($"details?{nameof(ShellTestPage.DoubleQueryParameter)}=1234")); - var testPage = (shell.CurrentItem.CurrentItem as IShellSectionController).PresentedPage as ShellTestPage; + var testPage = shell.CurrentPage as ShellTestPage; Assert.Equal(1234d, testPage.DoubleQueryParameter); } @@ -371,7 +371,7 @@ public async Task BasicShellParameterTest() }; await shell.GoToAsync(new ShellNavigationState($"details?{nameof(ShellTestPage.SomeQueryParameter)}=1234"), parameter); - var testPage = (shell.CurrentItem.CurrentItem as IShellSectionController).PresentedPage as ShellTestPage; + var testPage = shell.CurrentPage as ShellTestPage; Assert.Equal("1234", testPage.SomeQueryParameter); Assert.Equal(2d, testPage.DoubleQueryParameter); Assert.Equal(obj, testPage.ComplexObject); @@ -392,7 +392,7 @@ public async Task ExtraParametersDontGetRetained() }; await shell.GoToAsync(new ShellNavigationState($"details?{nameof(ShellTestPage.SomeQueryParameter)}=1234"), parameter); - var testPage = (shell.CurrentItem.CurrentItem as IShellSectionController).PresentedPage as ShellTestPage; + var testPage = shell.CurrentPage as ShellTestPage; await shell.Navigation.PushAsync(new ContentPage()); @@ -445,7 +445,7 @@ public async Task ExtraParametersArentReAppliedWhenNavigatingBackToShellContent( shell.CurrentItem = withParams; await Task.Yield(); - var testPage2 = (shell.CurrentItem.CurrentItem as IShellSectionController).PresentedPage as ShellTestPage; + var testPage2 = shell.CurrentPage as ShellTestPage; Assert.Null(testPage2.SomeQueryParameter); Assert.Null(testPage2.ComplexObject); Assert.Equal(testPage2, testPage); @@ -459,11 +459,13 @@ public async Task SingleUseQueryParametersReplaceQueryStringParams() Routing.RegisterRoute("details", typeof(ShellTestPage)); shell.Items.Add(item); - var parameter = new KeyValuePair( - $"{nameof(ShellTestPage.SomeQueryParameter)}", "4321"); + var parameter = new ShellNavigationQueryParameters() + { + {nameof(ShellTestPage.SomeQueryParameter), "4321" } + }; await shell.GoToAsync(new ShellNavigationState($"details?{nameof(ShellTestPage.SomeQueryParameter)}=1234"), parameter); - var testPage = (shell.CurrentItem.CurrentItem as IShellSectionController).PresentedPage as ShellTestPage; + var testPage = shell.CurrentPage as ShellTestPage; // Parameters passed in will win Assert.Equal("4321", testPage.SomeQueryParameter); From 1311f1c878174936afc7ef7fe39eced97b335e1e Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Fri, 30 Jun 2023 14:09:13 -0500 Subject: [PATCH 3/7] - modify unshipped bits --- .../net-android/PublicAPI.Unshipped.txt | 24 ++++++++++- .../PublicAPI/net-ios/PublicAPI.Unshipped.txt | 22 ++++++++++ .../net-maccatalyst/PublicAPI.Unshipped.txt | 22 ++++++++++ .../net-tizen/PublicAPI.Unshipped.txt | 22 ++++++++++ .../net-windows/PublicAPI.Unshipped.txt | 24 ++++++++++- .../PublicAPI/net/PublicAPI.Unshipped.txt | 24 ++++++++++- .../netstandard/PublicAPI.Unshipped.txt | 22 ++++++++++ src/Controls/src/Core/Shell/Shell.cs | 2 - src/Controls/src/Core/Shell/ShellContent.cs | 5 ++- .../Shell/ShellNavigationQueryParameters.cs | 29 +++++++++---- .../src/Core/Shell/ShellRouteParameters.cs | 34 ++++++++++++--- .../ShellParameterPassingTests.cs | 41 ++++++++++++++++++- .../tests/Core.UnitTests/ShellTestBase.cs | 5 ++- 13 files changed, 253 insertions(+), 23 deletions(-) diff --git a/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt index f3850cb322e9..96f9562abf8b 100644 --- a/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt @@ -99,4 +99,26 @@ override Microsoft.Maui.Controls.SearchBar.IsEnabledCore.get -> bool Microsoft.Maui.Controls.IValueConverter.Convert(object? value, System.Type! targetType, object? parameter, System.Globalization.CultureInfo! culture) -> object? Microsoft.Maui.Controls.IValueConverter.ConvertBack(object? value, System.Type! targetType, object? parameter, System.Globalization.CultureInfo! culture) -> object? ~static Microsoft.Maui.Controls.GridExtensions.Add(this Microsoft.Maui.Controls.Grid grid, Microsoft.Maui.IView view, int left, int right, int top, int bottom) -> void -~static Microsoft.Maui.Controls.GridExtensions.AddWithSpan(this Microsoft.Maui.Controls.Grid grid, Microsoft.Maui.IView view, int row = 0, int column = 0, int rowSpan = 1, int columnSpan = 1) -> void \ No newline at end of file +~static Microsoft.Maui.Controls.GridExtensions.AddWithSpan(this Microsoft.Maui.Controls.Grid grid, Microsoft.Maui.IView view, int row = 0, int column = 0, int rowSpan = 1, int columnSpan = 1) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Add(string! key, object! value) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Add(System.Collections.Generic.KeyValuePair item) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Clear() -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Contains(System.Collections.Generic.KeyValuePair item) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ContainsKey(string! key) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.CopyTo(System.Collections.Generic.KeyValuePair[]! array, int arrayIndex) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Count.get -> int +Microsoft.Maui.Controls.ShellNavigationQueryParameters.GetEnumerator() -> System.Collections.Generic.IEnumerator>! +Microsoft.Maui.Controls.ShellNavigationQueryParameters.IsReadOnly.get -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Keys.get -> System.Collections.Generic.ICollection! +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Remove(string! key) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Remove(System.Collections.Generic.KeyValuePair item) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters() -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters(System.Collections.Generic.IDictionary! dictionary) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters(System.Collections.Generic.IEnumerable>! collection) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].get -> object! +Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].set -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.TryGetValue(string! key, out object! value) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Values.get -> System.Collections.Generic.ICollection! +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task \ No newline at end of file diff --git a/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt index 3d5af1c1cc13..712b333e4c4f 100644 --- a/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt @@ -102,3 +102,25 @@ Microsoft.Maui.Controls.IValueConverter.ConvertBack(object? value, System.Type! *REMOVED*override Microsoft.Maui.Controls.Handlers.Compatibility.PhoneFlyoutPageRenderer.WillRotate(UIKit.UIInterfaceOrientation toInterfaceOrientation, double duration) -> void ~virtual Microsoft.Maui.Controls.Handlers.Items.ItemsViewController.DetermineCellReuseId(Foundation.NSIndexPath indexPath) -> string override Microsoft.Maui.Controls.Handlers.Items.ItemsViewHandler.GetDesiredSize(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size +Microsoft.Maui.Controls.ShellNavigationQueryParameters +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Add(string! key, object! value) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Add(System.Collections.Generic.KeyValuePair item) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Clear() -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Contains(System.Collections.Generic.KeyValuePair item) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ContainsKey(string! key) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.CopyTo(System.Collections.Generic.KeyValuePair[]! array, int arrayIndex) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Count.get -> int +Microsoft.Maui.Controls.ShellNavigationQueryParameters.GetEnumerator() -> System.Collections.Generic.IEnumerator>! +Microsoft.Maui.Controls.ShellNavigationQueryParameters.IsReadOnly.get -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Keys.get -> System.Collections.Generic.ICollection! +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Remove(string! key) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Remove(System.Collections.Generic.KeyValuePair item) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters() -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters(System.Collections.Generic.IDictionary! dictionary) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters(System.Collections.Generic.IEnumerable>! collection) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].get -> object! +Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].set -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.TryGetValue(string! key, out object! value) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Values.get -> System.Collections.Generic.ICollection! +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task \ No newline at end of file diff --git a/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt index 3d5af1c1cc13..712b333e4c4f 100644 --- a/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt @@ -102,3 +102,25 @@ Microsoft.Maui.Controls.IValueConverter.ConvertBack(object? value, System.Type! *REMOVED*override Microsoft.Maui.Controls.Handlers.Compatibility.PhoneFlyoutPageRenderer.WillRotate(UIKit.UIInterfaceOrientation toInterfaceOrientation, double duration) -> void ~virtual Microsoft.Maui.Controls.Handlers.Items.ItemsViewController.DetermineCellReuseId(Foundation.NSIndexPath indexPath) -> string override Microsoft.Maui.Controls.Handlers.Items.ItemsViewHandler.GetDesiredSize(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size +Microsoft.Maui.Controls.ShellNavigationQueryParameters +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Add(string! key, object! value) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Add(System.Collections.Generic.KeyValuePair item) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Clear() -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Contains(System.Collections.Generic.KeyValuePair item) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ContainsKey(string! key) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.CopyTo(System.Collections.Generic.KeyValuePair[]! array, int arrayIndex) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Count.get -> int +Microsoft.Maui.Controls.ShellNavigationQueryParameters.GetEnumerator() -> System.Collections.Generic.IEnumerator>! +Microsoft.Maui.Controls.ShellNavigationQueryParameters.IsReadOnly.get -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Keys.get -> System.Collections.Generic.ICollection! +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Remove(string! key) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Remove(System.Collections.Generic.KeyValuePair item) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters() -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters(System.Collections.Generic.IDictionary! dictionary) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters(System.Collections.Generic.IEnumerable>! collection) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].get -> object! +Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].set -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.TryGetValue(string! key, out object! value) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Values.get -> System.Collections.Generic.ICollection! +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task \ No newline at end of file diff --git a/src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt index 2f089f2bd8f8..f9e15bdee11d 100644 --- a/src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt @@ -85,3 +85,25 @@ Microsoft.Maui.Controls.Shapes.Shape.~Shape() -> void override Microsoft.Maui.Controls.Shapes.Shape.OnBindingContextChanged() -> void ~override Microsoft.Maui.Controls.ImageButton.OnPropertyChanged(string propertyName = null) -> void ~static Microsoft.Maui.Controls.Region.FromRectangles(System.Collections.Generic.IEnumerable rectangles) -> Microsoft.Maui.Controls.Region +Microsoft.Maui.Controls.ShellNavigationQueryParameters +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Add(string! key, object! value) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Add(System.Collections.Generic.KeyValuePair item) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Clear() -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Contains(System.Collections.Generic.KeyValuePair item) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ContainsKey(string! key) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.CopyTo(System.Collections.Generic.KeyValuePair[]! array, int arrayIndex) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Count.get -> int +Microsoft.Maui.Controls.ShellNavigationQueryParameters.GetEnumerator() -> System.Collections.Generic.IEnumerator>! +Microsoft.Maui.Controls.ShellNavigationQueryParameters.IsReadOnly.get -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Keys.get -> System.Collections.Generic.ICollection! +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Remove(string! key) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Remove(System.Collections.Generic.KeyValuePair item) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters() -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters(System.Collections.Generic.IDictionary! dictionary) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters(System.Collections.Generic.IEnumerable>! collection) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].get -> object! +Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].set -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.TryGetValue(string! key, out object! value) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Values.get -> System.Collections.Generic.ICollection! +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task \ No newline at end of file diff --git a/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt index f1fff8c5199b..5bec365a4352 100644 --- a/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt @@ -99,4 +99,26 @@ override Microsoft.Maui.Controls.SearchBar.IsEnabledCore.get -> bool Microsoft.Maui.Controls.IValueConverter.Convert(object? value, System.Type! targetType, object? parameter, System.Globalization.CultureInfo! culture) -> object? Microsoft.Maui.Controls.IValueConverter.ConvertBack(object? value, System.Type! targetType, object? parameter, System.Globalization.CultureInfo! culture) -> object? ~static Microsoft.Maui.Controls.GridExtensions.Add(this Microsoft.Maui.Controls.Grid grid, Microsoft.Maui.IView view, int left, int right, int top, int bottom) -> void -~static Microsoft.Maui.Controls.GridExtensions.AddWithSpan(this Microsoft.Maui.Controls.Grid grid, Microsoft.Maui.IView view, int row = 0, int column = 0, int rowSpan = 1, int columnSpan = 1) -> void \ No newline at end of file +~static Microsoft.Maui.Controls.GridExtensions.AddWithSpan(this Microsoft.Maui.Controls.Grid grid, Microsoft.Maui.IView view, int row = 0, int column = 0, int rowSpan = 1, int columnSpan = 1) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Add(string! key, object! value) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Add(System.Collections.Generic.KeyValuePair item) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Clear() -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Contains(System.Collections.Generic.KeyValuePair item) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ContainsKey(string! key) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.CopyTo(System.Collections.Generic.KeyValuePair[]! array, int arrayIndex) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Count.get -> int +Microsoft.Maui.Controls.ShellNavigationQueryParameters.GetEnumerator() -> System.Collections.Generic.IEnumerator>! +Microsoft.Maui.Controls.ShellNavigationQueryParameters.IsReadOnly.get -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Keys.get -> System.Collections.Generic.ICollection! +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Remove(string! key) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Remove(System.Collections.Generic.KeyValuePair item) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters() -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters(System.Collections.Generic.IDictionary! dictionary) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters(System.Collections.Generic.IEnumerable>! collection) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].get -> object! +Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].set -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.TryGetValue(string! key, out object! value) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Values.get -> System.Collections.Generic.ICollection! +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task \ No newline at end of file diff --git a/src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt index 4ef8570e7f7a..536f24f25dd5 100644 --- a/src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt @@ -87,4 +87,26 @@ override Microsoft.Maui.Controls.SearchBar.IsEnabledCore.get -> bool Microsoft.Maui.Controls.IValueConverter.Convert(object? value, System.Type! targetType, object? parameter, System.Globalization.CultureInfo! culture) -> object? Microsoft.Maui.Controls.IValueConverter.ConvertBack(object? value, System.Type! targetType, object? parameter, System.Globalization.CultureInfo! culture) -> object? ~static Microsoft.Maui.Controls.GridExtensions.Add(this Microsoft.Maui.Controls.Grid grid, Microsoft.Maui.IView view, int left, int right, int top, int bottom) -> void -~static Microsoft.Maui.Controls.GridExtensions.AddWithSpan(this Microsoft.Maui.Controls.Grid grid, Microsoft.Maui.IView view, int row = 0, int column = 0, int rowSpan = 1, int columnSpan = 1) -> void \ No newline at end of file +~static Microsoft.Maui.Controls.GridExtensions.AddWithSpan(this Microsoft.Maui.Controls.Grid grid, Microsoft.Maui.IView view, int row = 0, int column = 0, int rowSpan = 1, int columnSpan = 1) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Add(string! key, object! value) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Add(System.Collections.Generic.KeyValuePair item) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Clear() -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Contains(System.Collections.Generic.KeyValuePair item) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ContainsKey(string! key) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.CopyTo(System.Collections.Generic.KeyValuePair[]! array, int arrayIndex) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Count.get -> int +Microsoft.Maui.Controls.ShellNavigationQueryParameters.GetEnumerator() -> System.Collections.Generic.IEnumerator>! +Microsoft.Maui.Controls.ShellNavigationQueryParameters.IsReadOnly.get -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Keys.get -> System.Collections.Generic.ICollection! +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Remove(string! key) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Remove(System.Collections.Generic.KeyValuePair item) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters() -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters(System.Collections.Generic.IDictionary! dictionary) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters(System.Collections.Generic.IEnumerable>! collection) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].get -> object! +Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].set -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.TryGetValue(string! key, out object! value) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Values.get -> System.Collections.Generic.ICollection! +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task \ No newline at end of file diff --git a/src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Unshipped.txt index 43e1a5856203..84d5f4ac00e8 100644 --- a/src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Unshipped.txt @@ -13,6 +13,26 @@ Microsoft.Maui.Controls.PointerGestureRecognizer.PointerMovedCommandParameter.ge Microsoft.Maui.Controls.Region.Equals(Microsoft.Maui.Controls.Region other) -> bool Microsoft.Maui.Controls.Shapes.Matrix.Equals(Microsoft.Maui.Controls.Shapes.Matrix other) -> bool Microsoft.Maui.Controls.Shapes.Shape.~Shape() -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Add(string! key, object! value) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Add(System.Collections.Generic.KeyValuePair item) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Clear() -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Contains(System.Collections.Generic.KeyValuePair item) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ContainsKey(string! key) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.CopyTo(System.Collections.Generic.KeyValuePair[]! array, int arrayIndex) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Count.get -> int +Microsoft.Maui.Controls.ShellNavigationQueryParameters.GetEnumerator() -> System.Collections.Generic.IEnumerator>! +Microsoft.Maui.Controls.ShellNavigationQueryParameters.IsReadOnly.get -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Keys.get -> System.Collections.Generic.ICollection! +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Remove(string! key) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Remove(System.Collections.Generic.KeyValuePair item) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters() -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters(System.Collections.Generic.IDictionary! dictionary) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters(System.Collections.Generic.IEnumerable>! collection) -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].get -> object! +Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].set -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.TryGetValue(string! key, out object! value) -> bool +Microsoft.Maui.Controls.ShellNavigationQueryParameters.Values.get -> System.Collections.Generic.ICollection! Microsoft.Maui.Controls.VisualElement.~VisualElement() -> void override Microsoft.Maui.Controls.LayoutOptions.GetHashCode() -> int override Microsoft.Maui.Controls.Region.GetHashCode() -> int @@ -40,6 +60,8 @@ Microsoft.Maui.Controls.VisualElement.RefreshIsEnabledProperty() -> void override Microsoft.Maui.Controls.Button.IsEnabledCore.get -> bool override Microsoft.Maui.Controls.ImageButton.IsEnabledCore.get -> bool override Microsoft.Maui.Controls.SearchBar.IsEnabledCore.get -> bool +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task ~Microsoft.Maui.Controls.WebView.UserAgent.get -> string ~Microsoft.Maui.Controls.WebView.UserAgent.set -> void ~override Microsoft.Maui.Controls.ImageButton.OnPropertyChanged(string propertyName = null) -> void diff --git a/src/Controls/src/Core/Shell/Shell.cs b/src/Controls/src/Core/Shell/Shell.cs index 7c2c747a4f85..74235c2f0300 100644 --- a/src/Controls/src/Core/Shell/Shell.cs +++ b/src/Controls/src/Core/Shell/Shell.cs @@ -691,7 +691,6 @@ public Task GoToAsync(ShellNavigationState state, bool animate, IDictionary /// /// @@ -714,7 +713,6 @@ public Task GoToAsync(ShellNavigationState state, bool animate, ShellNavigationQ { return _navigationManager.GoToAsync(state, animate, false, parameters: new ShellRouteParameters(singleUseQueryParameter)); } -#pragma warning restore RS0016 // Add public types and members to the declared API public void AddLogicalChild(Element element) { diff --git a/src/Controls/src/Core/Shell/ShellContent.cs b/src/Controls/src/Core/Shell/ShellContent.cs index 712bda517d02..d0cbdcace7f2 100644 --- a/src/Controls/src/Core/Shell/ShellContent.cs +++ b/src/Controls/src/Core/Shell/ShellContent.cs @@ -287,7 +287,10 @@ static void ApplyQueryAttributes(object content, ShellRouteParameters query, She oldQuery = oldQuery ?? new ShellRouteParameters(); if (content is IQueryAttributable attributable) - attributable.ApplyQueryAttributes(query); + { + attributable + .ApplyQueryAttributes(query.GiveMeReadOnlyIfOnlyUsingShellNavigationQueryParameters()); + } if (content is BindableObject bindable && bindable.BindingContext != null && content != bindable.BindingContext) ApplyQueryAttributes(bindable.BindingContext, query, oldQuery); diff --git a/src/Controls/src/Core/Shell/ShellNavigationQueryParameters.cs b/src/Controls/src/Core/Shell/ShellNavigationQueryParameters.cs index 7b0e3f13b0b5..435f5606644d 100644 --- a/src/Controls/src/Core/Shell/ShellNavigationQueryParameters.cs +++ b/src/Controls/src/Core/Shell/ShellNavigationQueryParameters.cs @@ -1,12 +1,9 @@ -#nullable disable -using System; +using System; using System.Collections; using System.Collections.Generic; -using System.Collections.ObjectModel; namespace Microsoft.Maui.Controls { -#pragma warning disable RS0016 // Add public types and members to the declared API public class ShellNavigationQueryParameters : IDictionary { Dictionary _internal = new Dictionary(); @@ -28,8 +25,11 @@ public ShellNavigationQueryParameters(IDictionary dictionary) this.Add(item.Key, item.Value); } - internal void SetToReadOnly() => + internal ShellNavigationQueryParameters SetToReadOnly() + { _isReadonly = true; + return this; + } void CheckReadOnlyState() { @@ -55,11 +55,23 @@ public object this[string key] public bool IsReadOnly => _isReadonly; - public void Add(string key, object value) => _internal.Add(key, value); + public void Add(string key, object value) + { + CheckReadOnlyState(); + _internal.Add(key, value); + } - public void Add(KeyValuePair item) => _internal.Add(item.Key, item.Value); + public void Add(KeyValuePair item) + { + CheckReadOnlyState(); + _internal.Add(item.Key, item.Value); + } - public void Clear() => _internal.Clear(); + public void Clear() + { + CheckReadOnlyState(); + _internal.Clear(); + } public bool Contains(KeyValuePair item) => _internal.ContainsKey(item.Key); @@ -90,5 +102,4 @@ public bool TryGetValue(string key, out object value) IEnumerator IEnumerable.GetEnumerator() => _internal.GetEnumerator(); } -#pragma warning restore RS0016 // Add public types and members to the declared API } \ No newline at end of file diff --git a/src/Controls/src/Core/Shell/ShellRouteParameters.cs b/src/Controls/src/Core/Shell/ShellRouteParameters.cs index 29bdee2459eb..724300dfff88 100644 --- a/src/Controls/src/Core/Shell/ShellRouteParameters.cs +++ b/src/Controls/src/Core/Shell/ShellRouteParameters.cs @@ -8,7 +8,8 @@ namespace Microsoft.Maui.Controls { internal class ShellRouteParameters : Dictionary { - ShellNavigationQueryParameters _singleUseQueryParameters; + readonly ShellNavigationQueryParameters _singleUseQueryParameters = + new ShellNavigationQueryParameters(); public ShellRouteParameters() { @@ -16,7 +17,26 @@ public ShellRouteParameters() public ShellRouteParameters(ShellRouteParameters shellRouteParams) : base(shellRouteParams) { - _singleUseQueryParameters = shellRouteParams._singleUseQueryParameters; + foreach (var item in shellRouteParams._singleUseQueryParameters) + _singleUseQueryParameters[item.Key] = item.Value; + } + + internal IDictionary GiveMeReadOnlyIfOnlyUsingShellNavigationQueryParameters() + { + if (_singleUseQueryParameters.Count != this.Count) + return this; + + foreach (var item in this) + { + if (!_singleUseQueryParameters.ContainsKey(item.Key)) + { + return this; + } + } + + return + new ShellNavigationQueryParameters(_singleUseQueryParameters) + .SetToReadOnly(); } internal ShellRouteParameters(ShellRouteParameters query, string prefix) @@ -32,7 +52,8 @@ internal ShellRouteParameters(ShellRouteParameters query, string prefix) this.Add(key, q.Value); } - _singleUseQueryParameters = query._singleUseQueryParameters; + foreach (var item in query._singleUseQueryParameters) + _singleUseQueryParameters[item.Key] = item.Value; } internal ShellRouteParameters(IDictionary shellRouteParams) : base(shellRouteParams) @@ -44,12 +65,13 @@ internal ShellRouteParameters(ShellNavigationQueryParameters singleUseQueryParam foreach (var item in singleUseQueryParameters) this.Add(item.Key, item.Value); - _singleUseQueryParameters = singleUseQueryParameters; + foreach (var item in singleUseQueryParameters) + _singleUseQueryParameters[item.Key] = item.Value; } internal void ResetToQueryParameters() { - if (_singleUseQueryParameters is null) + if (_singleUseQueryParameters.Count == 0) return; foreach (var item in _singleUseQueryParameters) @@ -60,7 +82,7 @@ internal void ResetToQueryParameters() } } - _singleUseQueryParameters = null; + _singleUseQueryParameters.Clear(); } internal void SetQueryStringParameters(string query) diff --git a/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs b/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs index 8f34a24a5219..2822f146648b 100644 --- a/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs +++ b/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs @@ -377,6 +377,45 @@ public async Task BasicShellParameterTest() Assert.Equal(obj, testPage.ComplexObject); } + [Fact] + public async Task ValidateReadOnlyDictionary() + { + var obj = new object(); + var parameter = new ShellNavigationQueryParameters + { + {"DoubleQueryParameter", 2d }, + { "ComplexObject", obj} + }.SetToReadOnly(); + + Assert.Throws(() => parameter.Add("key", "value")); + Assert.Throws(() => parameter.Add(new KeyValuePair("key", "value"))); + Assert.Throws(() => parameter.Remove(parameter.First())); + Assert.Throws(() => parameter.Remove("DoubleQueryParameter")); + Assert.Throws(() => parameter["key"] = "value"); + Assert.Throws(() => parameter.Clear()); + } + + [Fact] + public async Task ShellNavigationQueryParametersPassedInAsReadOnly() + { + var shell = new Shell(); + var item = CreateShellItem(shellSectionRoute: "section2"); + Routing.RegisterRoute("details", typeof(ShellTestPage)); + shell.Items.Add(item); + var obj = new object(); + var parameter = new ShellNavigationQueryParameters + { + {"DoubleQueryParameter", 2d }, + { "ComplexObject", obj} + }; + + await shell.GoToAsync(new ShellNavigationState($"details"), parameter); + var testPage = shell.CurrentPage as ShellTestPage; + Assert.True(testPage.AppliedQueryAttributes[0].IsReadOnly); + Assert.False(parameter.IsReadOnly); + Assert.Single(testPage.AppliedQueryAttributes); + } + [Fact] public async Task ExtraParametersDontGetRetained() { @@ -385,7 +424,7 @@ public async Task ExtraParametersDontGetRetained() Routing.RegisterRoute("details", typeof(ShellTestPage)); shell.Items.Add(item); var obj = new object(); - var parameter = new ShellRouteParameters + var parameter = new ShellNavigationQueryParameters { {"DoubleQueryParameter", 2d }, { "ComplexObject", obj} diff --git a/src/Controls/tests/Core.UnitTests/ShellTestBase.cs b/src/Controls/tests/Core.UnitTests/ShellTestBase.cs index 2bbcfdfe8047..624fcc1d3ff6 100644 --- a/src/Controls/tests/Core.UnitTests/ShellTestBase.cs +++ b/src/Controls/tests/Core.UnitTests/ShellTestBase.cs @@ -132,7 +132,10 @@ protected override bool OnBackButtonPressed() public List> AppliedQueryAttributes = new List>(); public void ApplyQueryAttributes(IDictionary query) { - AppliedQueryAttributes.Add(new Dictionary(query)); + if (query is ShellNavigationQueryParameters param && param.IsReadOnly) + AppliedQueryAttributes.Add(query); + else + AppliedQueryAttributes.Add(new Dictionary(query)); } } From c828acb9f5bc581857124cdcbfd67e64fe65332f Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Fri, 30 Jun 2023 14:30:02 -0500 Subject: [PATCH 4/7] - fix api script --- .../src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt | 2 +- .../src/Core/Shell/ShellNavigationQueryParameters.cs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt index 5bec365a4352..3036c6b2ec88 100644 --- a/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt @@ -12,6 +12,7 @@ Microsoft.Maui.Controls.PointerGestureRecognizer.PointerMovedCommandParameter.ge *REMOVED*Microsoft.Maui.Controls.PointerGestureRecognizer.PointerExitedCommandParameter.get -> System.Windows.Input.ICommand! *REMOVED*Microsoft.Maui.Controls.PointerGestureRecognizer.PointerMovedCommandParameter.get -> System.Windows.Input.ICommand! Microsoft.Maui.Controls.Handlers.Items.StructuredItemsViewHandler.~StructuredItemsViewHandler() -> void +Microsoft.Maui.Controls.ShellNavigationQueryParameters.TryGetValue(string! key, out object! value) -> bool override Microsoft.Maui.Controls.Handlers.BoxViewHandler.NeedsContainer.get -> bool Microsoft.Maui.Controls.Handlers.BoxViewHandler Microsoft.Maui.Controls.Handlers.BoxViewHandler.BoxViewHandler() -> void @@ -118,7 +119,6 @@ Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParam Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParameters(System.Collections.Generic.IEnumerable>! collection) -> void Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].get -> object! Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].set -> void -Microsoft.Maui.Controls.ShellNavigationQueryParameters.TryGetValue(string! key, out object! value) -> bool Microsoft.Maui.Controls.ShellNavigationQueryParameters.Values.get -> System.Collections.Generic.ICollection! ~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task ~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task \ No newline at end of file diff --git a/src/Controls/src/Core/Shell/ShellNavigationQueryParameters.cs b/src/Controls/src/Core/Shell/ShellNavigationQueryParameters.cs index 435f5606644d..c71a6592474a 100644 --- a/src/Controls/src/Core/Shell/ShellNavigationQueryParameters.cs +++ b/src/Controls/src/Core/Shell/ShellNavigationQueryParameters.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.Maui.Controls { @@ -94,7 +95,11 @@ public bool Remove(KeyValuePair item) return (_internal as ICollection>).Remove(item); } +#if NETSTANDARD2_1 || NETSTANDARD2_0 public bool TryGetValue(string key, out object value) +#else + public bool TryGetValue(string key, [MaybeNullWhen(false)] out object value) +#endif { return _internal.TryGetValue(key, out value); } From 1cd7f31d9403bc30503735df0799f6f3aae52547 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Wed, 5 Jul 2023 12:01:10 -0500 Subject: [PATCH 5/7] - fix docs --- .../net-android/PublicAPI.Unshipped.txt | 4 +- .../PublicAPI/net-ios/PublicAPI.Unshipped.txt | 4 +- .../net-maccatalyst/PublicAPI.Unshipped.txt | 4 +- .../net-tizen/PublicAPI.Unshipped.txt | 4 +- .../net-windows/PublicAPI.Unshipped.txt | 4 +- .../PublicAPI/net/PublicAPI.Unshipped.txt | 4 +- .../netstandard/PublicAPI.Unshipped.txt | 4 +- src/Controls/src/Core/Shell/Shell.cs | 22 +++++----- src/Controls/src/Core/Shell/ShellContent.cs | 2 +- .../src/Core/Shell/ShellRouteParameters.cs | 43 ++++++++----------- 10 files changed, 43 insertions(+), 52 deletions(-) diff --git a/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt index 96f9562abf8b..1345f3d59640 100644 --- a/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt @@ -120,5 +120,5 @@ Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].get -> Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].set -> void Microsoft.Maui.Controls.ShellNavigationQueryParameters.TryGetValue(string! key, out object! value) -> bool Microsoft.Maui.Controls.ShellNavigationQueryParameters.Values.get -> System.Collections.Generic.ICollection! -~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task -~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task \ No newline at end of file +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters shellNavigationQueryParameters) -> System.Threading.Tasks.Task +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters shellNavigationQueryParameters) -> System.Threading.Tasks.Task \ No newline at end of file diff --git a/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt index 712b333e4c4f..e20c57a3fd5f 100644 --- a/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt @@ -122,5 +122,5 @@ Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].get -> Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].set -> void Microsoft.Maui.Controls.ShellNavigationQueryParameters.TryGetValue(string! key, out object! value) -> bool Microsoft.Maui.Controls.ShellNavigationQueryParameters.Values.get -> System.Collections.Generic.ICollection! -~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task -~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task \ No newline at end of file +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters shellNavigationQueryParameters) -> System.Threading.Tasks.Task +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters shellNavigationQueryParameters) -> System.Threading.Tasks.Task \ No newline at end of file diff --git a/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt index 712b333e4c4f..e20c57a3fd5f 100644 --- a/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt @@ -122,5 +122,5 @@ Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].get -> Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].set -> void Microsoft.Maui.Controls.ShellNavigationQueryParameters.TryGetValue(string! key, out object! value) -> bool Microsoft.Maui.Controls.ShellNavigationQueryParameters.Values.get -> System.Collections.Generic.ICollection! -~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task -~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task \ No newline at end of file +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters shellNavigationQueryParameters) -> System.Threading.Tasks.Task +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters shellNavigationQueryParameters) -> System.Threading.Tasks.Task \ No newline at end of file diff --git a/src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt index f9e15bdee11d..ea3bfe1d22cf 100644 --- a/src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt @@ -105,5 +105,5 @@ Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].get -> Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].set -> void Microsoft.Maui.Controls.ShellNavigationQueryParameters.TryGetValue(string! key, out object! value) -> bool Microsoft.Maui.Controls.ShellNavigationQueryParameters.Values.get -> System.Collections.Generic.ICollection! -~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task -~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task \ No newline at end of file +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters shellNavigationQueryParameters) -> System.Threading.Tasks.Task +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters shellNavigationQueryParameters) -> System.Threading.Tasks.Task \ No newline at end of file diff --git a/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt index 3036c6b2ec88..34a7f018db0b 100644 --- a/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt @@ -120,5 +120,5 @@ Microsoft.Maui.Controls.ShellNavigationQueryParameters.ShellNavigationQueryParam Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].get -> object! Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].set -> void Microsoft.Maui.Controls.ShellNavigationQueryParameters.Values.get -> System.Collections.Generic.ICollection! -~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task -~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task \ No newline at end of file +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters shellNavigationQueryParameters) -> System.Threading.Tasks.Task +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters shellNavigationQueryParameters) -> System.Threading.Tasks.Task \ No newline at end of file diff --git a/src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt index 536f24f25dd5..b1b5bde70fa8 100644 --- a/src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt @@ -108,5 +108,5 @@ Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].get -> Microsoft.Maui.Controls.ShellNavigationQueryParameters.this[string! key].set -> void Microsoft.Maui.Controls.ShellNavigationQueryParameters.TryGetValue(string! key, out object! value) -> bool Microsoft.Maui.Controls.ShellNavigationQueryParameters.Values.get -> System.Collections.Generic.ICollection! -~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task -~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task \ No newline at end of file +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters shellNavigationQueryParameters) -> System.Threading.Tasks.Task +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters shellNavigationQueryParameters) -> System.Threading.Tasks.Task \ No newline at end of file diff --git a/src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Unshipped.txt index 84d5f4ac00e8..9e7df06a02a5 100644 --- a/src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Unshipped.txt @@ -60,8 +60,8 @@ Microsoft.Maui.Controls.VisualElement.RefreshIsEnabledProperty() -> void override Microsoft.Maui.Controls.Button.IsEnabledCore.get -> bool override Microsoft.Maui.Controls.ImageButton.IsEnabledCore.get -> bool override Microsoft.Maui.Controls.SearchBar.IsEnabledCore.get -> bool -~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task -~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters singleUseQueryParameter) -> System.Threading.Tasks.Task +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, bool animate, Microsoft.Maui.Controls.ShellNavigationQueryParameters shellNavigationQueryParameters) -> System.Threading.Tasks.Task +~Microsoft.Maui.Controls.Shell.GoToAsync(Microsoft.Maui.Controls.ShellNavigationState state, Microsoft.Maui.Controls.ShellNavigationQueryParameters shellNavigationQueryParameters) -> System.Threading.Tasks.Task ~Microsoft.Maui.Controls.WebView.UserAgent.get -> string ~Microsoft.Maui.Controls.WebView.UserAgent.set -> void ~override Microsoft.Maui.Controls.ImageButton.OnPropertyChanged(string propertyName = null) -> void diff --git a/src/Controls/src/Core/Shell/Shell.cs b/src/Controls/src/Core/Shell/Shell.cs index 74235c2f0300..5d6243ab0150 100644 --- a/src/Controls/src/Core/Shell/Shell.cs +++ b/src/Controls/src/Core/Shell/Shell.cs @@ -692,26 +692,26 @@ public Task GoToAsync(ShellNavigationState state, bool animate, IDictionary - /// + /// This method navigates to a and returns a that will complete once the navigation animation. /// - /// - /// Any parameters passed here won't be reused when the page is navigated back to + /// Defines the path for Shell to navigate to. + /// Parameters to use for this specific navigation operation. /// - public Task GoToAsync(ShellNavigationState state, ShellNavigationQueryParameters singleUseQueryParameter) + public Task GoToAsync(ShellNavigationState state, ShellNavigationQueryParameters shellNavigationQueryParameters) { - return _navigationManager.GoToAsync(state, null, false, parameters: new ShellRouteParameters(singleUseQueryParameter)); + return _navigationManager.GoToAsync(state, null, false, parameters: new ShellRouteParameters(shellNavigationQueryParameters)); } /// - /// + /// This method navigates to a and returns a . /// - /// - /// - /// Any parameters passed here won't be reused when the page is navigated back to + /// Defines the path for Shell to navigate to. + /// Indicates if your transition is animated + /// Parameters to use for this specific navigation operation. /// - public Task GoToAsync(ShellNavigationState state, bool animate, ShellNavigationQueryParameters singleUseQueryParameter) + public Task GoToAsync(ShellNavigationState state, bool animate, ShellNavigationQueryParameters shellNavigationQueryParameters) { - return _navigationManager.GoToAsync(state, animate, false, parameters: new ShellRouteParameters(singleUseQueryParameter)); + return _navigationManager.GoToAsync(state, animate, false, parameters: new ShellRouteParameters(shellNavigationQueryParameters)); } public void AddLogicalChild(Element element) diff --git a/src/Controls/src/Core/Shell/ShellContent.cs b/src/Controls/src/Core/Shell/ShellContent.cs index d0cbdcace7f2..c0c06b8d0ef3 100644 --- a/src/Controls/src/Core/Shell/ShellContent.cs +++ b/src/Controls/src/Core/Shell/ShellContent.cs @@ -289,7 +289,7 @@ static void ApplyQueryAttributes(object content, ShellRouteParameters query, She if (content is IQueryAttributable attributable) { attributable - .ApplyQueryAttributes(query.GiveMeReadOnlyIfOnlyUsingShellNavigationQueryParameters()); + .ApplyQueryAttributes(query.ToReadOnlyIfUsingShellNavigationQueryParameters()); } if (content is BindableObject bindable && bindable.BindingContext != null && content != bindable.BindingContext) diff --git a/src/Controls/src/Core/Shell/ShellRouteParameters.cs b/src/Controls/src/Core/Shell/ShellRouteParameters.cs index 724300dfff88..d1ab184e1f6e 100644 --- a/src/Controls/src/Core/Shell/ShellRouteParameters.cs +++ b/src/Controls/src/Core/Shell/ShellRouteParameters.cs @@ -8,7 +8,7 @@ namespace Microsoft.Maui.Controls { internal class ShellRouteParameters : Dictionary { - readonly ShellNavigationQueryParameters _singleUseQueryParameters = + readonly ShellNavigationQueryParameters _shellNavigationQueryParameters = new ShellNavigationQueryParameters(); public ShellRouteParameters() @@ -17,26 +17,17 @@ public ShellRouteParameters() public ShellRouteParameters(ShellRouteParameters shellRouteParams) : base(shellRouteParams) { - foreach (var item in shellRouteParams._singleUseQueryParameters) - _singleUseQueryParameters[item.Key] = item.Value; + foreach (var item in shellRouteParams._shellNavigationQueryParameters) + _shellNavigationQueryParameters[item.Key] = item.Value; } - internal IDictionary GiveMeReadOnlyIfOnlyUsingShellNavigationQueryParameters() + internal IDictionary ToReadOnlyIfUsingShellNavigationQueryParameters() { - if (_singleUseQueryParameters.Count != this.Count) - return this; + if (_shellNavigationQueryParameters.Count > 0) + return new ShellNavigationQueryParameters(_shellNavigationQueryParameters) + .SetToReadOnly(); - foreach (var item in this) - { - if (!_singleUseQueryParameters.ContainsKey(item.Key)) - { - return this; - } - } - - return - new ShellNavigationQueryParameters(_singleUseQueryParameters) - .SetToReadOnly(); + return this; } internal ShellRouteParameters(ShellRouteParameters query, string prefix) @@ -52,29 +43,29 @@ internal ShellRouteParameters(ShellRouteParameters query, string prefix) this.Add(key, q.Value); } - foreach (var item in query._singleUseQueryParameters) - _singleUseQueryParameters[item.Key] = item.Value; + foreach (var item in query._shellNavigationQueryParameters) + _shellNavigationQueryParameters[item.Key] = item.Value; } internal ShellRouteParameters(IDictionary shellRouteParams) : base(shellRouteParams) { } - internal ShellRouteParameters(ShellNavigationQueryParameters singleUseQueryParameters) + internal ShellRouteParameters(ShellNavigationQueryParameters shellNavigationQueryParameterss) { - foreach (var item in singleUseQueryParameters) + foreach (var item in shellNavigationQueryParameterss) this.Add(item.Key, item.Value); - foreach (var item in singleUseQueryParameters) - _singleUseQueryParameters[item.Key] = item.Value; + foreach (var item in shellNavigationQueryParameterss) + _shellNavigationQueryParameters[item.Key] = item.Value; } internal void ResetToQueryParameters() { - if (_singleUseQueryParameters.Count == 0) + if (_shellNavigationQueryParameters.Count == 0) return; - foreach (var item in _singleUseQueryParameters) + foreach (var item in _shellNavigationQueryParameters) { if (this.ContainsKey(item.Key)) { @@ -82,7 +73,7 @@ internal void ResetToQueryParameters() } } - _singleUseQueryParameters.Clear(); + _shellNavigationQueryParameters.Clear(); } internal void SetQueryStringParameters(string query) From afaeb18ffa1afe5d5b7ac527692c6c1fb318c779 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Wed, 5 Jul 2023 13:06:30 -0500 Subject: [PATCH 6/7] - correctly build up returned parameters --- src/Controls/src/Core/Shell/ShellRouteParameters.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Controls/src/Core/Shell/ShellRouteParameters.cs b/src/Controls/src/Core/Shell/ShellRouteParameters.cs index d1ab184e1f6e..f3a91dd6850a 100644 --- a/src/Controls/src/Core/Shell/ShellRouteParameters.cs +++ b/src/Controls/src/Core/Shell/ShellRouteParameters.cs @@ -24,8 +24,17 @@ public ShellRouteParameters(ShellRouteParameters shellRouteParams) : base(shellR internal IDictionary ToReadOnlyIfUsingShellNavigationQueryParameters() { if (_shellNavigationQueryParameters.Count > 0) - return new ShellNavigationQueryParameters(_shellNavigationQueryParameters) - .SetToReadOnly(); + { + var returnValue = new ShellNavigationQueryParameters(_shellNavigationQueryParameters); + + foreach (var item in this) + { + if (!returnValue.ContainsKey(item.Key)) + returnValue.Add(item.Key, item.Value); + + return returnValue.SetToReadOnly(); + } + } return this; } From bd596571603ee42783cd3a3e1bd90226cdd6f15f Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Wed, 5 Jul 2023 13:10:44 -0500 Subject: [PATCH 7/7] - fix --- src/Controls/src/Core/Shell/ShellRouteParameters.cs | 4 ++-- .../tests/Core.UnitTests/ShellParameterPassingTests.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Controls/src/Core/Shell/ShellRouteParameters.cs b/src/Controls/src/Core/Shell/ShellRouteParameters.cs index f3a91dd6850a..495f55b02ac3 100644 --- a/src/Controls/src/Core/Shell/ShellRouteParameters.cs +++ b/src/Controls/src/Core/Shell/ShellRouteParameters.cs @@ -31,9 +31,9 @@ internal IDictionary ToReadOnlyIfUsingShellNavigationQueryParame { if (!returnValue.ContainsKey(item.Key)) returnValue.Add(item.Key, item.Value); - - return returnValue.SetToReadOnly(); } + + return returnValue.SetToReadOnly(); } return this; diff --git a/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs b/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs index 2822f146648b..0e2f31b61a09 100644 --- a/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs +++ b/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs @@ -427,7 +427,7 @@ public async Task ExtraParametersDontGetRetained() var parameter = new ShellNavigationQueryParameters { {"DoubleQueryParameter", 2d }, - { "ComplexObject", obj} + {"ComplexObject", obj} }; await shell.GoToAsync(new ShellNavigationState($"details?{nameof(ShellTestPage.SomeQueryParameter)}=1234"), parameter);