[Shell] fixes navigate to a relative URI (#4977)
This commit is contained in:
Родитель
cc7e7eb8c2
Коммит
e3360aa8c9
|
@ -127,7 +127,60 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
Assert.That(shell.CurrentState.Location.ToString(), Is.EqualTo("app:///s/two/tabfour/content/"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task RelativeGoTo()
|
||||
{
|
||||
var shell = new Shell
|
||||
{
|
||||
Route = "s"
|
||||
};
|
||||
|
||||
var one = new ShellItem { Route = "one" };
|
||||
var two = new ShellItem { Route = "two" };
|
||||
|
||||
var tab11 = MakeSimpleShellSection("tab11", "content");
|
||||
var tab12 = MakeSimpleShellSection("tab12", "content");
|
||||
var tab21 = MakeSimpleShellSection("tab21", "content");
|
||||
var tab22 = MakeSimpleShellSection("tab22", "content");
|
||||
var tab23 = MakeSimpleShellSection("tab23", "content");
|
||||
|
||||
one.Items.Add(tab11);
|
||||
one.Items.Add(tab12);
|
||||
|
||||
two.Items.Add(tab21);
|
||||
two.Items.Add(tab22);
|
||||
two.Items.Add(tab23);
|
||||
|
||||
shell.Items.Add(one);
|
||||
shell.Items.Add(two);
|
||||
|
||||
await shell.GoToAsync("app:///s/two/tab21/");
|
||||
|
||||
await shell.GoToAsync("/tab22");
|
||||
Assert.That(shell.CurrentState.Location.ToString(), Is.EqualTo("app:///s/two/tab22/content/"));
|
||||
|
||||
await shell.GoToAsync("tab21");
|
||||
Assert.That(shell.CurrentState.Location.ToString(), Is.EqualTo("app:///s/two/tab21/content/"));
|
||||
|
||||
await shell.GoToAsync("/tab23");
|
||||
Assert.That(shell.CurrentState.Location.ToString(), Is.EqualTo("app:///s/two/tab23/content/"));
|
||||
|
||||
await shell.GoToAsync("../one/tab11");
|
||||
Assert.That(shell.CurrentState.Location.ToString(), Is.EqualTo("app:///s/one/tab11/content/"));
|
||||
|
||||
await shell.GoToAsync("/eee/hm../../../../two/../one/../two/tab21");
|
||||
Assert.That(shell.CurrentState.Location.ToString(), Is.EqualTo("app:///s/two/tab21/content/"));
|
||||
|
||||
await shell.GoToAsync(new ShellNavigationState("../one/tab11"));
|
||||
Assert.That(shell.CurrentState.Location.ToString(), Is.EqualTo("app:///s/one/tab11/content/"));
|
||||
|
||||
await shell.GoToAsync(new ShellNavigationState($"../two/tab23/content?{nameof(ShellTestPage.SomeQueryParameter)}=1234"));
|
||||
Assert.That(shell.CurrentState.Location.ToString(), Is.EqualTo("app:///s/two/tab23/content/"));
|
||||
Assert.AreEqual("1234", (two.CurrentItem.CurrentItem.Content as ShellTestPage).SomeQueryParameter);
|
||||
|
||||
await shell.GoToAsync(new ShellNavigationState($"../one/tab11#fragment"));
|
||||
Assert.That(shell.CurrentState.Location.ToString(), Is.EqualTo("app:///s/one/tab11/content/"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task NavigationWithQueryStringWhenPageMatchesBindingContext()
|
||||
|
|
|
@ -6,6 +6,7 @@ using System.Linq;
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
|
@ -324,6 +325,35 @@ namespace Xamarin.Forms
|
|||
|
||||
public static Shell CurrentShell => Application.Current?.MainPage as Shell;
|
||||
|
||||
Uri GetAbsoluteUri(Uri relativeUri)
|
||||
{
|
||||
if (CurrentItem == null)
|
||||
throw new InvalidOperationException("Relative path is used after selecting Current item.");
|
||||
|
||||
var parseUri = Regex.Match(relativeUri.OriginalString, @"(?<u>.+?)(\?(?<q>.+?))?(#(?<f>.+))?$").Groups;
|
||||
var url = parseUri["u"].Value;
|
||||
var query = parseUri["q"].Value;
|
||||
var fragment = parseUri["f"].Value;
|
||||
|
||||
Element item = CurrentItem;
|
||||
var list = new List<string> { url.Trim('/') };
|
||||
while (item != null)
|
||||
{
|
||||
var route = Routing.GetRoute(item)?.Trim('/');
|
||||
if (string.IsNullOrEmpty(route))
|
||||
break;
|
||||
list.Insert(0, route);
|
||||
item = item.Parent;
|
||||
}
|
||||
var parentUriBuilder = new UriBuilder(RouteScheme)
|
||||
{
|
||||
Path = string.Join("/", list),
|
||||
Query = query,
|
||||
Fragment = fragment
|
||||
};
|
||||
return parentUriBuilder.Uri;
|
||||
}
|
||||
|
||||
public async Task GoToAsync(ShellNavigationState state, bool animate = true)
|
||||
{
|
||||
// FIXME: This should not be none, we need to compute the delta and set flags correctly
|
||||
|
@ -333,7 +363,7 @@ namespace Xamarin.Forms
|
|||
|
||||
_accumulateNavigatedEvents = true;
|
||||
|
||||
var uri = state.Location;
|
||||
var uri = state.Location.IsAbsoluteUri ? state.Location : GetAbsoluteUri(state.Location);
|
||||
var queryString = uri.Query;
|
||||
var queryData = ParseQueryString(queryString);
|
||||
var path = uri.AbsolutePath;
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace Xamarin.Forms
|
|||
public Uri Location { get; set; }
|
||||
|
||||
public ShellNavigationState() { }
|
||||
public ShellNavigationState(string location) => Location = new Uri(location);
|
||||
public ShellNavigationState(string location) => Location = new Uri(location, UriKind.RelativeOrAbsolute);
|
||||
public ShellNavigationState(Uri location) => Location = location;
|
||||
public static implicit operator ShellNavigationState(Uri uri) => new ShellNavigationState(uri);
|
||||
public static implicit operator ShellNavigationState(string value) => new ShellNavigationState(value);
|
||||
|
|
Загрузка…
Ссылка в новой задаче