Xamarin 应用程序无法返回

Xamarin application not navigating back

问题

这是过程:

  1. Select 来自列表的 category

  2. 加载Tasks page.

  3. Tasks 根据上一页选择的 categoryId 加载。 (可以导航回 Category page ✔️)

  4. Select 来自列表的 Task

  5. 加载Task Page.

  6. 页面上加载了任务详细信息。 (无法导航回“任务”页面 ❌)

视频

问题

我不明白为什么我无法返回页面。我该如何解决这个问题?

代码

CategoriesViewModel

public class CategoriesViewModel : BaseViewModel
{
    public ObservableCollection<CategoryModel> Categories { get; } = new ObservableCollection<CategoryModel>();

    public Command LoadCategoriesCommand { get; }
    public Command<CategoryModel> SelectedCategory { get; }

    public CategoriesViewModel()
    {
        Title = "Categories";

        LoadCategoriesCommand = new Command(async () => await LoadCategories());
        SelectedCategory = new Command<CategoryModel>(OnSelectedCategory);
    }

    private async Task LoadCategories()
    {
        IsBusy = true;
        try
        {
            Categories.Clear();

            var categories = await DatabaseService.GetCategoriesAsync();
            foreach (var category in categories)
            {
                this.Categories.Add(category);
            }
        }
        catch (Exception)
        {

            throw;
        }
        finally
        {
            IsBusy = false;
        }
    }

    private async void OnSelectedCategory(CategoryModel category)
    {
        if (category == null)
            return;

        await Shell.Current.GoToAsync($"{nameof(TasksPage)}?{nameof(TasksViewModel.CategoryId)}={category.CategoryId}");
    }

    public void OnAppearing()
    {
        IsBusy = true;
    }
}

TasksViewModel

[QueryProperty(nameof(CategoryId), nameof(CategoryId))]
public class TasksViewModel : BaseViewModel
{
    public ObservableCollection<TaskModel> Tasks { get; } = new ObservableCollection<TaskModel>();

    private int categoryId;
    public int CategoryId
    {
        get { return categoryId; }
        set
        {
            categoryId = value;
        }
    }

    public Command LoadTasksCommand { get; set; }
    public Command<TaskModel> SelectedTask { get; set; }

    public TasksViewModel()
    {
        Title = "Tasks";
        LoadTasksCommand = new Command(async () => await LoadTasks());
        SelectedTask = new Command<TaskModel>(OnSelectedTask);
    }

    private async Task LoadTasks()
    {
        IsBusy = true;
        try
        {
            this.Tasks.Clear();

            var tasks = await DatabaseService.GetTasksAsync(CategoryId);
            foreach (var task in tasks)
            {
                this.Tasks.Add(task);
            }
        }
        catch (Exception)
        {

            throw;
        }
        finally
        {
            IsBusy = false;
        }
    }

    private async void OnSelectedTask(TaskModel task)
    {
        if (task == null)
            return;

        await Shell.Current.GoToAsync($"{nameof(TaskPage)}?{nameof(TaskViewModel.TaskId)}={task.TaskId}");
    }

    public void OnAppearing()
    {
        IsBusy = true;
    }
}

TaskViewModel

[QueryProperty(nameof(TaskId), nameof(TaskId))]
public class TaskViewModel : BaseViewModel
{
    private int taskId;

    public int TaskId
    {
        get { return taskId; }
        set
        {
            taskId = value;
        }
    }

    private string taskTitle;

    public string TaskTitle
    {
        get { return taskTitle; }
        set
        {
            taskTitle = value;
            OnPropertyChanged(nameof(TaskTitle));
        }
    }

    private string description;

    public string Description
    {
        get { return description; }
        set
        {
            description = value;
            OnPropertyChanged(nameof(Description));
        }
    }

    public Command LoadTaskCommand { get; }

    public TaskViewModel()
    {
        LoadTaskCommand = new Command(async () => await LoadTask());
    }

    private async Task LoadTask()
    {
        IsBusy = true;
        try
        {
            var task = await DatabaseService.GetTaskAsync(TaskId);
            this.TaskTitle = task.Title;
            this.Description = task.Description;
        }
        catch (Exception)
        {

            throw;
        }
        finally
        {
            IsBusy = false;
        }
    }

    public void OnAppearing()
    {
        IsBusy = true;
    }
}

更新 1

我尝试替换 TasksViewModel 中的这行代码:

await Shell.Current.GoToAsync($"{nameof(TaskPage)}?{nameof(TaskViewModel.TaskId)}={task.TaskId}");

对此:

await Shell.Current.Navigation.PushAsync(new AboutPage());

同样的结果。

更新 2

根据请求的评论,这里是 TaskPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:vm="clr-namespace:SomeProject.ViewModels"
             x:Class="SomeProject.Views.Task.TaskPage"
             Title="{Binding TaskTitle}">
    <ContentPage.Content>
        <RefreshView x:DataType="vm:TaskViewModel"
                     Command="{Binding LoadTaskCommand}"
                     IsRefreshing="{Binding IsBusy, Mode=TwoWay}">
            <StackLayout>
                <Label Text="{Binding Description}" />
            </StackLayout>
        </RefreshView>
    </ContentPage.Content>
</ContentPage>

TaskPage.xaml.cs:

public partial class TaskPage : ContentPage
{
    TaskViewModel _viewModel;
    public TaskPage()
    {
        InitializeComponent();
        BindingContext = _viewModel = new TaskViewModel();
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();
        _viewModel.OnAppearing();
    }
}

更新 3

根据请求的评论,这里是 routes:

public AppShell()
{
    InitializeComponent();
    Routing.RegisterRoute(nameof(CategoriesView), typeof(CategoriesView));
    Routing.RegisterRoute(nameof(TasksPage), typeof(TasksPage));
    Routing.RegisterRoute(nameof(TaskPage), typeof(TaskPage));
}

检查您的收银机路线。

https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/shell/navigation#register-page-routes

In the Shell subclass constructor, or any other location that runs before a route is invoked, additional routes can be explicitly registered for any pages that aren't represented in the Shell visual hierarchy

我已经 CategoryPageAppShell.xaml.cs 注册了 AppShell.xaml 也是这样:

<ShellContent Route="CategoryPage" ContentTemplate="{DataTemplate local:CategoryPage}" />

只能在一个或另一个中注册一个路由。