Xamarin Forms AppShell 如何 return 到上一页

Xamarin Forms AppShell How return to previous page

我看到很多关于此类主题的帖子,但 none 似乎适用于我的问题。我没有导航页面,我有一个汉堡菜单——所以 Push/PopAsync() 似乎不是答案。而且我不想转到特定页面,我想返回上一页(无论它是什么)所以 GoToAsync() 似乎不是答案。

用于 Android 的 Xamarin 应用程序和 iOS 未来某个地方的 UWP。下面的问题描述是Android特有的;它在 UWP 上的工作方式略有不同。

我想在汉堡菜单中放置一个帮助条目,它将把用户带到默认浏览器中的帮助页面。汉堡包菜单似乎只转到应用程序页面,所以我定义了一个“虚拟”视图页面,显示“正在加载...”并在其 OnAppearing() 方法中发出 Browser.OpenAsync() ,这非常有效。问题在于,用户希望在单击“帮助” 之前,“后退”按钮会将他或她带到他们所在的页面 。我尝试了几件事。我已经接近以下内容,但它不能正常工作:

在我的每个其他视图的 OnAppearing() 中,我调用了一个方法,将 Current.MainPage.CurrentItem 的值保存在静态中。然后在 OpenAsync() 之后的帮助页面中,我将 Current.MainPage.CurrentItem 设置为帮助页面之前最后一页的设置。

Console.WriteLine("#### HelpPage loading Web Help");
_ = State.DisplayHelpPage(this, "MainHelp");        // _ = await Browser.OpenAsync(uri, blo);
Console.WriteLine("#### HelpPage returning to previous page");
State.ReloadPreviousPage();     // Current.MainPage).CurrentItem = lastFlyoutItem;

差不多可以了。第一次单击汉堡菜单中的帮助时,我得到

#### HelpPage loading Web Help
#### HelpPage returning to previous page
#### HelpPage loading Web Help
#### HelpPage returning to previous page

网页加载完美。但是,当我单击“后退”按钮时,它会再次显示。很明显我的OnAppearing()方法已经被驱动了两次,我不明白。

如果我再次单击“后退”按钮,我将返回应用程序中的上一页,就像我想要的那样。下次我在 Hamburger 菜单中单击“帮助”时,它会将我带到没有网页的虚拟“查看”页面。显然,我的 OnAppearing() 根本没有被驱动。但在那之后它完美地工作。我可以转到任何应用程序页面,然后单击菜单中的帮助。我得到了网页,然后“后退”按钮将我带回到应用程序和页面。在 UWP 中,浏览器当然不会加载到应用程序视图之上,而且我似乎每次都看到它被加载两次。

所以...我应该做些什么不同的事情?为什么我的 OnAppearing() 被驱动了两次,然后就完全不被驱动了……然后就如我所料?

这个答案有几个部分:

  1. 将上一页放到导航堆栈中。这是通过拦截路由“//HelpPage”并将其替换为不是 Shell.
  2. 的子路由来完成的
  3. 记住“FakePageVisible”,所以我们知道在 OnResume 中执行“PopAsync”,当应用 returns 来自浏览器时。
  4. (可选)“进入”标志可防止进入浏览器两次。

App.xaml.cs:

public partial class App : Application
{

    public App()
    {
        InitializeComponent();

        MainPage = new AppShell();
    }

    protected override void OnResume()
    {
        if (HelpPage.FakePageVisible) {
            HelpPage.FakePageVisible = false;
            var shell = MainPage as AppShell;
            if (shell != null) {
                shell.Navigation.PopAsync();
            }
        }
    }
}

AppShell.xaml.cs:

public partial class AppShell : Xamarin.Forms.Shell
{
    public AppShell()
    {
        InitializeComponent();
        // Define a route that isn't a child of Shell.
        Routing.RegisterRoute("Help2", typeof(HelpPage));
    }

    protected override void OnNavigating(ShellNavigatingEventArgs args)
    {
        base.OnNavigating(args);

        if (args.Current != null) {
            if (args.Source == ShellNavigationSource.ShellItemChanged) {
                if (args.Target.Location.OriginalString == "//HelpPage") {
                    // Cancel the original route.
                    args.Cancel();
                    Device.BeginInvokeOnMainThread(() => {
                        // Used by the next OnAppearing.
                        HelpPage.Entering = true;
                        // Go there by a route that isn't a child of Shell.
                        // Doing so, pushes our previous location on to Navigation stack.
                        Shell.Current.GoToAsync("Help2");
                    });
                }
            }
        }
    }
}

HelpPage.xaml.cs:

public partial class HelpPage : ContentPage
{
    public static bool Entering;
    public static bool FakePageVisible;
    
    protected override void OnAppearing
    {
        // Make sure this only happens once (just in case).
        if (Entering) {
            Entering = false;
            FakePageVisible = true;
            Xamarin.Essentials.Browser.OpenAsync("https://aka.ms/xamarin-quickstart");
        }
    }
}

对于一个简单的演示,此代码通过 HelpPage 中的静态变量进行通信。根据您的情况重新考虑因素。