簡體   English   中英

毛伊島 Shell 向后導航

[英]Maui Shell backwards navigation

我希望用戶能夠將產品從一個位置移動到另一個位置。 完成后,我想 go 返回產品頁面,因為他可能會繼續從同一位置移動產品。 我有兩個略有不同的場景。

場景 1:

//SourceAisle/SourceLocation/Products/TargetAisle/TargetLocation

場景 2:

//SourceAisle/SourceLocation/Products/FavoriteLocation

在這兩種情況下,當用戶完成后,我想 go 回到

//SourceAisle/SourceLocation/Products

我可以在場景 1 中執行Shell.Current.GoToAsync("../..") ,在場景 2 中Shell.Current.GoToAsync("..")但我希望有一些共享邏輯,即go 返回產品頁

根據文檔,可以使用/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));
    }
}

通道和位置頁面用於源和目標,並且有一些 state 來處理這兩種不同的情況,但這不在這個問題的 scope 中。

從 LocationsViewModel 我調用await Shell.Current.GoToAsync("Products") ,從 ProductsViewModel 我調用await Shell.Current.GoToAsync("TargetAisle")等等。 我認為這就是所謂的相對路由而不是絕對路由,不確定我是否應該做不同的事情。

您可以編寫這樣的命令,它可以識別頁面名稱,然后導航到目標頁面。

 public class MyViewModel: ContentPage
    {
        public ICommand NavigateCommand { get; private set; }
        public MyViewModel()
        {
            NavigateCommand = new Command<Type>(
             async (Type pageType) =>
             {
                 Page page = (Page)Activator.CreateInstance(pageType);
                 await Navigation.PushAsync(page);
             });
        }
    }

這是命令的樣式。

<TextCell Text="Entry"
          Command="{Binding NavigateCommand}"
          CommandParameter="{x:Type views:CustomizeSpecificEntryPage}" />

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM