Обратная навигация в оболочке Мауи
Я хочу, чтобы пользователь мог перемещать продукты из одного места в другое. Когда закончите, я хочу вернуться на страницу продуктов, потому что он, вероятно, будет продолжать перемещать продукты из того же места. У меня есть два немного разных сценария.
Сценарий 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 .