使用 ApplicationView 显示多个视图

通过让用户在单独的窗口中查看应用的独立组成部分,来帮助他们提高工作效率。 如果你为应用创建多个窗口,每个窗口都独立运作。 任务栏会分别显示每个窗口。 用户可以独立地移动、调整大小、显示和隐藏应用窗口,并且可以在应用窗口间切换,就像它们是单独的应用一样。 每个窗口都在它自己的线程中运行。

重要的 APIApplicationViewSwitcherCreateNewView

什么是视图?

应用视图是指将线程与应用用来显示内容的窗口进行 1:1 配对。 它由 Windows.ApplicationModel.Core.CoreApplicationView 对象表示。

视图由 CoreApplication 对象进行管理。 调用 CoreApplication.CreateNewView 来创建 CoreApplicationView 对象。 CoreApplicationView 将同时引入 CoreWindowCoreDispatcher(存储在 CoreWindowDispatcher 属性中)。 你可以将 CoreApplicationView 视为 Windows 运行时用来与核心 Windows 系统进行交互的对象。

通常情况下,你不会直接使用 CoreApplicationView。 相反,Windows 运行时会在 Windows.UI.ViewManagement 命名空间中提供 ApplicationView 类。 该类将提供你在应用与窗口化系统进行交互时使用的属性、方法和事件。 若要使用 ApplicationView,请调用静态 ApplicationView.GetForCurrentView 方法,这样会获取与当前 CoreApplicationView 的线程紧密相关的 ApplicationView 实例。

而且,XAML 框架会将 CoreWindow 对象包装在 Windows.UI.XAML.Window 对象中。 在 XAML 应用中,你通常会与 Window 对象交互,而不是直接使用 CoreWindow

显示新视图

尽管每个应用布局都是独特的,但我们建议在可预测的位置(例如,可在新窗口中打开的内容的右上角)包含一个“新建窗口”按钮。 此外请考虑加入“在新窗口中打开”的上下文菜单选项。

让我们了解一下创建新视图的步骤。 在此处,启动新视图以响应按钮单击。

private async void Button_Click(object sender, RoutedEventArgs e)
{
    CoreApplicationView newView = CoreApplication.CreateNewView();
    int newViewId = 0;
    await newView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        Frame frame = new Frame();
        frame.Navigate(typeof(SecondaryPage), null);   
        Window.Current.Content = frame;
        // You have to activate the window in order to show it later.
        Window.Current.Activate();

        newViewId = ApplicationView.GetForCurrentView().Id;
    });
    bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewId);
}

显示新视图

  1. 调用 CoreApplication.CreateNewView 来为视图内容创建新窗口和线程。

    CoreApplicationView newView = CoreApplication.CreateNewView();
    
  2. 跟踪新视图的 Id。 稍后使用此选项来显示视图。

    你可能需要考虑在你的应用中生成一些基础结构以帮助跟踪你创建的视图。 有关示例, ViewLifetimeControl 请参阅 MultipleViews 示例中的 类。

    int newViewId = 0;
    
  3. 在新线程上,填充窗口。

    使用 CoreDispatcher.RunAsync 方法在新视图的 UI 线程上安排工作。 使用 lambda 表达式将函数作为参数传递到 RunAsync 方法。 你在 lambda 函数中执行的工作将在新视图的线程上进行。

    在 XAML中,通常向 WindowContent 属性添加 Frame,然后将 Frame 导航到你已为其定义应用内容的 XAML Page。 有关框架和页面的详细信息,请参阅两个页面之间的对等导航

    在填充新 Window 后,必须调用 WindowActivate 方法才能在稍后显示 Window。 这项工作在新视图的线程上进行,因此会激活新 Window

    最后,获取新视图的 Id,用于稍后显示该视图。 同样,此项工作在新视图的线程上进行,因此 ApplicationView.GetForCurrentView 会获取新视图的 Id

    await newView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        Frame frame = new Frame();
        frame.Navigate(typeof(SecondaryPage), null);   
        Window.Current.Content = frame;
        // You have to activate the window in order to show it later.
        Window.Current.Activate();
    
        newViewId = ApplicationView.GetForCurrentView().Id;
    });
    
  4. 通过调用 ApplicationViewSwitcher.TryShowAsStandaloneAsync 显示新视图。

    在创建新视图之后,你可以通过调用 ApplicationViewSwitcher.TryShowAsStandaloneAsync 方法,将其显示在新窗口中。 此方法的 viewId 参数是唯一标识你的应用中每个视图的整数。 通过使用 ApplicationView.Id 属性或 ApplicationView.GetApplicationViewIdForWindow 方法检索视图 Id

    bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewId);
    

主视图

应用启动时创建的第一个视图称为主视图。 此视图存储于 CoreApplication.MainView 属性中,而且其 IsMain 属性为 True。 不要创建此视图;应用会创建它。 主视图的线程可充当应用的管理器,而且所有应用激活事件都会在此线程上传送。

如果打开了辅助视图,主视图的窗口可以隐藏(例如,通过单击窗口标题栏中的关闭 (x) 按钮),但它的线程仍保持活动状态。 在主视图的 Window 上调用 Close 会导致 InvalidOperationException 发生。 (使用 Application.Exit 关闭你的应用。)如果主视图的线程终止,则应用关闭。

辅助视图

其他视图都是辅助视图,包括你通过调用应用代码中的 CreateNewView 创建的所有视图。 主视图和辅助视图均存储于 CoreApplication.Views 集合中。 通常情况下,创建辅助视图以响应用户操作。 在某些情况中,系统会为你的应用创建辅助视图。

注意

你可以使用 Windows 分配的访问权限功能在展台模式中运行应用。 执行此操作时,系统会创建一个辅助视图以显示锁屏界面上方的应用 UI。 不允许使用应用创建的辅助视图,因此如果你尝试在展台模式下显示自己的辅助视图,将引发异常。

从一个视图切换到另一个视图

考虑为用户提供一种途径来从辅助窗口导航回父窗口。 要执行此操作,请使用 ApplicationViewSwitcher.SwitchAsync 方法。 从要从中切换的窗口的线程调用此方法,并传递要切换到的窗口的视图 ID。

await ApplicationViewSwitcher.SwitchAsync(viewIdToShow);

当你使用 SwitchAsync 时,你可以选择是否想要关闭初始窗口,并通过指定 ApplicationViewSwitchingOptions 的值将它从任务栏中删除。