我希望用户能够将产品从一个位置移动到另一个位置。完成后,我希望回到产品页面,因为他很可能会继续在同一位置移动产品。这里有两种稍微不同的情况。
情景1:
在用户完成操作后,无论哪种情况,我都希望返回到原来的界面。
情景1:
//SourceAisle/SourceLocation/Products/TargetAisle/TargetLocation
场景2:
//SourceAisle/SourceLocation/Products/FavoriteLocation
在用户完成操作后,无论哪种情况,我都希望返回到原来的界面。
//SourceAisle/SourceLocation/Products
在方案1中,我可以使用 Shell.Current.GoToAsync("../..")
,在方案2中使用 Shell.Current.GoToAsync("..")
,但我想要一些共享的逻辑,例如返回到产品页面。
根据文档,可以使用/route或///route向后搜索,但我不确定它如何工作。我不想"推送"任何新页面,我基本上想要"弹出"所有页面,直到显示我想要的页面。
使用Shell导航是否可能?
注
我在旧的Xamarin项目中创建了一个扩展方法,完全可以实现以上操作,但如果Shell提供本地方式来实现,我更愿意不使用它。
// await Shell.Current.Navigation.PopToAsync<ProductsPage>();
internal static class NavigationExtensions
{
private static readonly SemaphoreSlim _semaphore = new (1, 1);
public static async Task PopToAsync<T>(this INavigation nav, Page nextPage = null, bool animated = true) where T : Page
{
await _semaphore.WaitAsync();
try
{
bool exists = nav.NavigationStack
.Where((p, i) => i <= nav.NavigationStack.Count - 2)
.Any(p => p is T);
if (!exists)
throw new ArgumentException($"The specified page {typeof(T).Name} does not exist in the stack");
for (var index = nav.NavigationStack.Count - 2; index > 0; index--)
{
if (nav.NavigationStack[index] is T)
break;
nav.RemovePage(nav.NavigationStack[index]);
}
if (nextPage is not null)
nav.InsertPageBefore(nextPage, nav.NavigationStack[nav.NavigationStack.Count - 1]);
await nav.PopAsync(animated);
}
finally
{
_semaphore.Release();
}
}
}
编辑
AppShell.xaml
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
x:Class="MyApp.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:MyApp.Views">
<FlyoutItem Route="SourceAisle" Title="Stock Movement">
<ShellContent ContentTemplate="{DataTemplate views:AislesPage}" />
</FlyoutItem>
</Shell>
AppShell.xaml.cs
public partial class AppShell : Shell
{
public AppShell()
{
InitializeComponent();
Routing.RegisterRoute("SourceAisle", typeof(AislesPage));
Routing.RegisterRoute("SourceLocation", typeof(LocationsPage));
Routing.RegisterRoute("Products", typeof(ProductsPage));
Routing.RegisterRoute("TargetAisle", typeof(AislesPage));
Routing.RegisterRoute("TargetLocation", typeof(LocationsPage));
Routing.RegisterRoute("FavoriteLocation", typeof(FavoritesPage));
}
}
走道和位置页面用于源和目标,有一些状态来处理两种不同的情况,但这超出了本问题的范围。
从LocationsViewModel中调用await Shell.Current.GoToAsync("Products")
,从ProductsViewModel中调用await Shell.Current.GoToAsync("TargetAisle")
等等。我认为这被称为相对路由而不是绝对路由,不确定是否应该以不同的方式处理。
//A/B/X
和//A/B/Y/Z
,我想知道是否存在一种方法可以返回到//A/B
。 - Arthur Rey//route
的描述:*"...匹配的页面将替换导航堆栈。"* 如果您不想继续推送更多页面,请在前面添加//
。 - ToolmakerSteveShell.Current.GoToAsync("B?id=10")
的东西)。从 X 或 Z 中调用Shell.Current.GoToAsync("//A/B")
确实会跳转到页面 B,但其 QueryProperty 为空。我想这是有道理的,因为我正在替换导航堆栈。调用Shell.Current.GoToAsync("..")
或Shell.Current.GoToAsync("../..")
是有效的,因为我正在返回到堆栈上的现有页面。也许我想要的并不存在,但我想将 返回 1 或 2 页 的逻辑变成 返回到 B。 - Arthur Rey