当前位置: 首页 > news >正文

理解 UWP 视图的概念,让 UWP 应用显示多个窗口(多视图)

UWP 应用多是一个窗口完成所有业务的,事实上我也推荐使用这种单一窗口的方式。不过,总有一些特别的情况下我们需要用到不止一个窗口,那么 UWP 中如何使用多窗口呢?


本文内容

    • 为什么 UWP 需要多窗口?
    • UWP 视图的概念
    • UWP 多窗口
    • 管理多个 UWP 视图

为什么 UWP 需要多窗口?

多窗口在传统 Win32 的开发当中是司空见惯的事儿了,不过我个人非常不喜欢,因为 Windows 系统上的多窗口太多坑。以下是我以前写的关于传统多窗口开发中的一些坑(除此之外还有更多):

  • 关闭模态窗口后,父窗口居然跑到了其他窗口的后面
  • WPF 程序无法触摸操作?我们一起来找原因和解决方法!

使用多窗口的原因很简单 —— 允许用户多任务处理。从这个角度来说,传统 Win32 使用“模态”多窗口的方式简直是低效的同时还带来 Bug!

微软官方文档中列举了一些例子:例如一边写邮件一边参考以往的邮件;一边看正在播放的音乐一边浏览播放列表;一次性打开多份文章然后稍后一起阅读等。

UWP 视图的概念

在学习如何编写 UWP 多窗口之前,我们需要了解一些 UWP 视图(View)的概念。

在 CoreApplication/Application、CoreWindow/Window 之间的区别 一文中,我描述了 UWP 视图的一些概念:

CoreApplication 管理一个 UWP 应用中的所有视图(View),而 CoreApplication 直接管理的视图是 CoreApplicationView;也就是说,UWP 应用 CoreApplication 管理所有的应用视图 CoreApplicationView。而一个 CoreApplicationView 包含一个窗口和一个线程调度模型,即 CoreWindowCoreDispatcher

CoreWindow 就是我们所理解的窗口。为了方便使用,Windows.UI.XAML.Window 类型封装了这个 CoreWindowCoreDispatcher 是基于消息循环的线程调度模型,正是因为有了消息循环,所以此窗口才能一直显示而不被销毁。

在 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序 一文中,我们也能体会到 CoreApplicationCoreWindow 之间的关系,了解消息循环在应用中的作用。

在这里插入图片描述

UWP 多窗口

在了解到 UWP 视图的概念之后,严格意义上说,这一节的标题应该叫做 “UWP 多视图”。

我画了一个思维导图来描述它们之间的关系。CoreApplication 有静态方法 CreateNewView,调用后能够创建新的 CoreApplicationView,这包含一个完整的 CoreWindowCoreDispatcher

在这里插入图片描述

创建并显示一个新 CoreApplicationView 的代码如下:

private async void OnLoaded(object sender, RoutedEventArgs e)
{
    // 创建一个 CoreApplicationView,即新的应用视图。
    var applicationView = CoreApplication.CreateNewView();

    // 一个应用视图有自己的 Id,稍后我们创建应用视图的时候,需要记录这个 Id。
    int newViewId = 0;

    // 使用新应用视图的 CoreDispatcher 线程调度模型来执行新视图中的操作。
    await applicationView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        // 在新的应用视图中,我们将新的窗口内容设置为 ThePageInNewView 页面。
        Frame frame = new Frame();
        frame.Navigate(typeof(ThePageInNewView), null);
        Window.Current.Content = frame;
        Window.Current.Activate();

        // 记录新应用视图的 Id,这样才能稍后切换。
        newViewId = ApplicationView.GetForCurrentView().Id;
    });

    // 使用刚刚记录的新应用视图 Id 显示新的应用视图。
    var viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewId);
}

创建完后的效果如下图:

UWP 多窗口

管理多个 UWP 视图

我们平时开发 UWP 应用的时候很少去关心 CoreApplicationView,因为默认情况下 UWP 能为我们做很多管理应用视图的工作。

CoreApplication 有一个 MainView 属性,即我们一开始运行 UWP 应用时的那个应用视图。如果我们有不止一个应用视图显示出来,那么这时点击主窗口的关闭按钮将不再是关闭,而是隐藏。如果要关闭,需要调用 Application.Exit

CoreApplicationViews 属性储存所有的 CoreApplicationView,我们可以使用此集合来管理多个视图。使用 ApplicationViewSwitcher.SwitchAsync 并传入视图 Id 可以切换视图的显示。

await ApplicationViewSwitcher.SwitchAsync(viewIdToShow);

参考资料

  • Show multiple views for an app - UWP app developer - Microsoft Docs

我的博客会首发于 https://blog.walterlv.com/,而 CSDN 会从其中精选发布,但是一旦发布了就很少更新。

如果在博客看到有任何不懂的内容,欢迎交流。我搭建了 dotnet 职业技术学院 欢迎大家加入。

知识共享许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:https://walterlv.blog.csdn.net/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。

相关文章:

  • UWP 扩展/自定义标题栏的方法,一些概念和一些注意事项
  • 图片点击放大,你的网页也能做到!
  • UWP 应用中 CoreApplication / Application, CoreWindow / Window 之间的区别
  • 使用 C# 代码创建快捷方式文件
  • 发布了一款库(或工具包),如何持续地编写更新日志(ChangeLog)?
  • Windows 无法删除文件夹 —— 访问被拒绝 / 因为目录不是空的
  • 如何精准地用打印机在贺卡或邀请函上打字
  • .NET/C# 推荐一个我设计的缓存类型(适合缓存反射等耗性能的操作,附用法)
  • 使用 Postman 调试 ASP.NET Core 开发的 API
  • 只有你能 new 出来!.NET 隐藏构造函数的 n 种方法(Builder Pattern / 构造器模式)
  • UWP 中的各种文件路径(用户、缓存、漫游、安装……)
  • 使用并解析 OPML 格式的订阅列表来转移自己的 RSS 订阅(解析篇)
  • 使用并解析 OPML 格式的订阅列表来转移自己的 RSS 订阅(概念篇)
  • csproj 文件中那个空的 NuGetPackageImportStamp 是干什么的?
  • C#/.NET 中 Thread.Sleep(0), Task.Delay(0), Thread.Yield(), Task.Yield() 不同的执行效果和用法建议
  • IE9 : DOM Exception: INVALID_CHARACTER_ERR (5)
  • [数据结构]链表的实现在PHP中
  • 【技术性】Search知识
  • Android优雅地处理按钮重复点击
  • Electron入门介绍
  • JavaScript设计模式之工厂模式
  • Linux Process Manage
  • niucms就是以城市为分割单位,在上面 小区/乡村/同城论坛+58+团购
  • Sass Day-01
  • Selenium实战教程系列(二)---元素定位
  • Spark学习笔记之相关记录
  • WebSocket使用
  • 分布式任务队列Celery
  • 搞机器学习要哪些技能
  • 基于阿里云移动推送的移动应用推送模式最佳实践
  • 那些年我们用过的显示性能指标
  • 使用putty远程连接linux
  • 原生Ajax
  • # centos7下FFmpeg环境部署记录
  • ###项目技术发展史
  • #1015 : KMP算法
  • (20)目标检测算法之YOLOv5计算预选框、详解anchor计算
  • (pojstep1.3.1)1017(构造法模拟)
  • (超详细)语音信号处理之特征提取
  • (定时器/计数器)中断系统(详解与使用)
  • (原創) 如何刪除Windows Live Writer留在本機的文章? (Web) (Windows Live Writer)
  • (转)iOS字体
  • (转)程序员技术练级攻略
  • ***汇编语言 实验16 编写包含多个功能子程序的中断例程
  • .NET Core MongoDB数据仓储和工作单元模式封装
  • .NET HttpWebRequest、WebClient、HttpClient
  • .NET 中选择合适的文件打开模式(CreateNew, Create, Open, OpenOrCreate, Truncate, Append)
  • .ui文件相关
  • /3GB和/USERVA开关
  • /dev/VolGroup00/LogVol00:unexpected inconsistency;run fsck manually
  • /usr/lib/mysql/plugin权限_给数据库增加密码策略遇到的权限问题
  • @data注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)
  • @html.ActionLink的几种参数格式
  • [145] 二叉树的后序遍历 js
  • [Android 数据通信] android cmwap接入点