| File: Shell\ShellNavigationState.cs | Web Access |
| Project: src\src\Controls\src\Core\Controls.Core.csproj (Microsoft.Maui.Controls) |
#nullable disable using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; namespace Microsoft.Maui.Controls { /// <include file="../../../docs/Microsoft.Maui.Controls/ShellNavigationState.xml" path="Type[@FullName='Microsoft.Maui.Controls.ShellNavigationState']/Docs/*" /> [DebuggerDisplay("Location = {Location}")] [TypeConverter(typeof(ShellNavigationStateTypeConverter))] public class ShellNavigationState { Uri _fullLocation; internal Uri FullLocation { get => _fullLocation; set { _fullLocation = value; } } /// <include file="../../../docs/Microsoft.Maui.Controls/ShellNavigationState.xml" path="//Member[@MemberName='Location']/Docs/*" /> public Uri Location { get; private set; } /// <include file="../../../docs/Microsoft.Maui.Controls/ShellNavigationState.xml" path="//Member[@MemberName='.ctor'][1]/Docs/*" /> public ShellNavigationState() { } /// <include file="../../../docs/Microsoft.Maui.Controls/ShellNavigationState.xml" path="//Member[@MemberName='.ctor'][2]/Docs/*" /> public ShellNavigationState(string location) : this(location, true) { } internal ShellNavigationState(string location, bool trimForUser) { var uri = ShellUriHandler.CreateUri(location); if (uri.IsAbsoluteUri) uri = new Uri($"/{uri.PathAndQuery}", UriKind.Relative); FullLocation = uri; if (trimForUser) Location = TrimDownImplicitAndDefaultPaths(FullLocation); else Location = FullLocation; } /// <include file="../../../docs/Microsoft.Maui.Controls/ShellNavigationState.xml" path="//Member[@MemberName='.ctor'][3]/Docs/*" /> public ShellNavigationState(Uri location) { FullLocation = location; Location = TrimDownImplicitAndDefaultPaths(FullLocation); } public static implicit operator ShellNavigationState(Uri uri) => new ShellNavigationState(uri); public static implicit operator ShellNavigationState(string value) => new ShellNavigationState(value); static Uri TrimDownImplicitAndDefaultPaths(Uri uri) { uri = ShellUriHandler.FormatUri(uri, null); // don't trim relative pushes if (!uri.OriginalString.StartsWith("//", StringComparison.Ordinal)) return uri; string[] parts = uri.OriginalString.TrimEnd(Routing.PathSeparator[0]).Split(Routing.PathSeparator[0]); List<string> toKeep = new List<string>(); // iterate over the shellitem/section/content for (int i = 2; i < 5 && i < parts.Length; i++) { if (!(Routing.IsDefault(parts[i])) && !(Routing.IsImplicit(parts[i]))) { toKeep.Add(parts[i]); } else if (i == 4) { // if all the routes are default then just put the last // shell content page as the route if (toKeep.Count == 0) toKeep.Add(parts[i]); } } // Always include pushed pages for (int i = 5; i < parts.Length; i++) { toKeep.Add(parts[i]); } toKeep.Insert(0, ""); toKeep.Insert(0, ""); return new Uri(string.Join(Routing.PathSeparator, toKeep), UriKind.Relative); } private sealed class ShellNavigationStateTypeConverter : TypeConverter { public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) => false; public override object ConvertTo(ITypeDescriptorContext context, CultureInfo cultureInfo, object value, Type destinationType) => throw new NotSupportedException(); public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) => sourceType == typeof(string) || sourceType == typeof(Uri); public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) => value switch { string str => (ShellNavigationState)str, Uri uri => (ShellNavigationState)uri, _ => throw new NotSupportedException(), }; } } }