Обратная навигация в оболочке Мауи

Я хочу, чтобы пользователь мог перемещать продукты из одного места в другое. Когда закончите, я хочу вернуться на страницу продуктов, потому что он, вероятно, будет продолжать перемещать продукты из того же места. У меня есть два немного разных сценария.

Сценарий 1:

      //SourceAisle/SourceLocation/Products/TargetAisle/TargetLocation

Сценарий 2:

      //SourceAisle/SourceLocation/Products/FavoriteLocation

В обоих сценариях, когда пользователь закончит работу, я хочу вернуться к

      //SourceAisle/SourceLocation/Products

я мог бы сделатьShell.Current.GoToAsync("../..")в сценарии 1 иShell.Current.GoToAsync("..")в сценарии 2, но я хотел бы иметь некоторую общую логику, т.е. вернуться на страницу продуктов.

Согласно документации можно выполнять поиск в обратном направлении, используя либо /route, либо ///route , но я не уверен, что понимаю, как это работает. Я не хочу «нажимать» какую-либо новую страницу, я в основном хочу «выталкивать» все страницы до страницы, которую я хочу отобразить.

Возможно ли использовать навигацию Shell?

ПРИМЕЧАНИЯ

Я создал методы расширения в более старом проекте Xamarin, который делает именно то, что описано выше, но я бы предпочел не использовать его, если оболочка предоставляет собственный способ сделать это.

      // 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")и так далее. Я думаю, что это то, что называется относительной маршрутизацией, а не абсолютной, не уверен, что я должен делать что-то по-другому.

2 ответа

Вы можете написать такую ​​команду, которая может распознать имя страницы, а затем перейти на целевую страницу.

       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}" />

Я думаю, вы можете передавать параметры в Routes, примерно так:

      string myValue = "ParameterToPass";
await Shell.Current.GoToAsync($"myLittleParameter?name={myValue}");

Это ссылка на документацию:https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/shell/navigation?view=net-maui-7.0#pass-data .

Другие вопросы по тегам