Windows App一般情况下,同一时刻只能有一个应用程序实例在运行,为了在特殊需求下可以同时呈现不同的UI,SDK提供了多视图操作支持。

应用程序可以创建新的应用视图,以新的视图为基础可以呈现与主视图不同的内容,但又不影响主视图的UI。这些视图既可以在同一个窗口中切换,也可以用新的窗口来呈现新的视图。这些窗口,用户可以拖放到不同的虚拟桌面中。

其实,视图的创建、切换、显示都不难,主要的难点在于完成这些操作所需要的类型被分布在不同的命名空间中,故不熟悉SDK的朋友可能找不到。

视图管理相关的API主要分布在以下两个命名空间下:

Windows.ApplicationModel.Core
 Windows.UI.ViewManagement

Core下面主要用到两个类。CoreApplication类负责创建视图,调用CreateNewView方法可以创建一个新的视图,创建后以CoreApplicationView对象返回。已创建的视图在CoreApplication.Views列表中,在应用程序运行期间,所有被创建的视图都在这个列表中,所以,还是节约一下资源,不要乱创建视图。

另外,在Windows.UI.ViewManagement命名空间下,也有几个类,也是用来操作视图,比较重要,上面的几个Core是用于创建视图,而ViewManagement下的类都是用来操作具体的某一个视图的。

ApplicationView类用于获取视图ID,设置视图标题等,其中,依靠ApplicationViewTitleBar类还可以自定窗口标题栏、标题栏按钮的背景颜色和前景颜色。

要在新窗口上显示某个视图,或者切换视图,都由ApplicationViewSwitcher类来完成,它是静态的,直接可以拿来耍,不用实例化。

下面我做了个例子,这个例子在主视图上放了几个网站链接,点击某个链接后,可以在新窗口中打开浏览目标网页。

核心代码如下:

            // 创建新的视图
CoreApplicationView newView = null;
if (CoreApplication.Views.Count > )
{
newView = CoreApplication.Views[];
}
// 如果没有这个视图,就创一个
if (newView == null)
{
newView = CoreApplication.CreateNewView();
} int newViewID = default(int); // 初始化视图
// 注意,必须在对应的线程上执行
await newView.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
() =>
{
// 获取视图ID,有两种方法
// 方法一:GetApplicationViewIdForWindow法,注意线程要对应
// Window必须是与当前视图关联的窗口
// int viewID = ApplicationView.GetApplicationViewIdForWindow(newView.CoreWindow);
// 方法二:最简单
// 因为当前执行的代码就在新视图的UI线程上的
// 所以GetForCurrentView所返回的就是刚创建的新视图
ApplicationView theView = ApplicationView.GetForCurrentView();
// 设置一下新窗口的标题(可选)
theView.Title = content;
// 必须记下视图ID
newViewID = theView.Id;
// 初始化视图的UI
ucDisplayPage uc = Window.Current.Content as ucDisplayPage;
if (uc == null)
{
uc = new ucDisplayPage();
uc.HorizontalAlignment = HorizontalAlignment.Stretch;
uc.VerticalAlignment = VerticalAlignment.Stretch;
uc.MinWidth = 450d;
uc.MinHeight = 300d;
Window.Current.Content = uc;
}
uc.TargetWebpageUri = uri;
Window.Current.Activate();
// 必须调用Activate方法,否则视图不能显示
/*
注意:
在App类中,Window.Current获取的是主视图(程序刚启动时,至少要有一个视图,不然用户连毛都看不见了)所在的窗口。
而因为此处的代码是在新创建的视图的UI线程上执行的,故Window.Current自然获取的是新视图所在的窗口。
*/
});
// 开始显示新视图
bool b = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewID); if (b)
{
// 成功显示新视图
}
else
{
// 视图显示失败
}

这里面其实没什么难点,关键点是你要理解。 CoreApplication.CreateNewView创建视图这个应该不难理解,但是在初始化新视图的UI时,一定一定一定要700%注意,每个视图都会由一个独立的UI线程来管理。所以,你的代码是在主视图里面写的,你不能直接在主视图中访问新视图,必须要从与新视图(CoreApplicationView对象)关联的Dispatcher来执行。

在插入到Dispatcher队列的代码中,Window.Current所指的已经不是主视图的窗口了,在App类中访问Window.Current当然返回的是主窗口,但是由于视图分布在不同的UI线程上,在新视图的Dispatcher中执行的代码,Window.Current得到的是新窗口的引用。

这时候可以和平时一样,给窗口的Content属性设置UI对象,安排新窗口要显示的内容。我的例子中用的是一个用户控件(User Control),这个不用我多介绍,凡是搞过Win开发的,不管你是WPF也好,WinForms也罢,肯定知道用户控件,就是用现有的控件进行二次组装,比重新开发一个控件方便。

由于使用ApplicationViewSwitcher来显示或切换视图时用的是视图ID(整数,很多时候是个负值,如-3122),因此我们必须获取新视图的ID号,才能用ApplicationViewSwitcher类来显示它。

一种方法是在Dispatcher插入的代码中访问ApplicationView.GetApplicationViewIdForWindow方法,它可以从新视图所属的窗口中获取到视图ID。

另一种最简单的方法是直接用ApplicationView.GetForCurrentView方法得到当前视图的引用,因为这行代码是写在新视图的UI线程上的,所以它获取到的自然是新视图的引用。GetForCurrentView方法在哪个线程上调用,它就获取那个线程关联的视图

最后一个关键点是,在新视图的线程上安排好窗口要显示的内容后,一定要调用窗口的Activate方法,保证窗口被激活,否则窗口会永远停留在初始屏幕。

在Win 8.1的时候,你不调用Activate方法也无所谓,因为8x的应用是全屏的,而10x的应用是既可以全屏,也可以窗口化的,所以,你一定要调用Activate方法。原理和做法与初始化App的OnLaunch方法中一样。

好了,关键点给大家分析了一下,重点是大家自己能不能理解,编程这玩意儿就是这样,理解了就轻松,不理解就脑痛。

下面来运行一下,点击主窗口上的链接,可以在新窗口中打开网页。而且你可以把新窗口拖到其他虚拟桌面上。

示例源代码下载:http://files.cnblogs.com/files/tcjiaan/MultiViewApp.zip

【Win 10应用开发】多窗口视图的更多相关文章

  1. 【Win 10 应用开发】启动远程设备上的应用

    这个功能必须在“红石-1”(build 14393)以上的系统版中才能使用,运行在一台设备上的应用,可以通过URI来启动另一台设备上的应用.激活远程应用需要以下前提: 系统必须是build 14393 ...

  2. 【Win 10 应用开发】导入.pfx证书

    这个功能其实并不常用,一般开发较少涉及到证书,不过,简单了解一下还是有必要的. 先来说说制作测试证书的方法,这里老周讲两种方法,可以生成用于测试的.pfx文件. 产生证书,大家都知道有个makecer ...

  3. 【Win 10应用开发】Adaptive磁贴模板的XML文档结构

    在若干天之前,老周给大家讲了Adaptive Toast通知的XML模板,所以相应地,今天老周给大家介绍一下Adaptive磁贴的新XML模板. 同样道理,你依旧可以使用8.1时候的磁贴模板,在win ...

  4. 【Win 10应用开发】认识一下UAP项目

    Windows 10 SDK预览版需要10030以上版本号的Win 10预览版系统才能使用.之前我安装的9926的系统,然后安装VS 2015 CTP 6,再装Win 10 SDK,但是在新建项目后, ...

  5. 【Win 10 应用开发】RTM版的UAP项目解剖

    Windows 10 发布后,其实SDK也偷偷地在VS的自定义安装列表中出现了,今天开发人员中心也更新了下载.正式版的SDK在API结构上和以前预览的时候是一样的,只是版本变成10240罢了,所以大家 ...

  6. 【Win 10 应用开发】在代码中加载文本资源

    记得前一次,老周给大伙,不,小伙伴们介绍了如何填写 .resw 文件,并且在 XAML 中使用 x:Uid 标记来加载.也顺便给大伙儿分析了运行时是如何解析 .resw 文件的. 本来说好了,后续老周 ...

  7. 【Win 10应用开发】延迟共享

    延迟共享是啥呢,这么说吧,就是在应用程序打开共享面板选择共享目标时,不会设置要共享的数据,而是等到共享目标请求数据时,才会发送数据,而且,延迟操作可以在后台进行. 这样说似乎过于抽象,最好的诠释方法, ...

  8. 【Win 10 应用开发】Toast通知激活应用——前台&后台

    老周最近热衷于讲故事,接下来还是讲故事时间. 有人问我:你上大学的时候,有加入过学生会吗?读大学有没有必要加入学生会? 哎哟,这怎么回答呢,从短期来说,加入学生会有点用,至少可以娱乐一下,运气好的话, ...

  9. 【Win 10 应用开发】UI Composition 札记(一):视图框架的实现

    在开始今天的内容之前,老周先说一个问题,这个问题记得以前有人提过的. 设置 Windows.ApplicationModel.Core.CoreApplicationView.TitleBar.Ext ...

随机推荐

  1. 第二天ci项目规划 数据库设计

    第二天ci项目规划 数据库设计 商品 + 用户 + 订单 数据库设计思想和方法 关于商品品牌 ,分类 ,属性 如何表示 用一个字段 还是再设计一张表 品牌和商品 是一种信息 还是两种信息 一张表一般只 ...

  2. 第二天ci项目规划 前后台分离

    第二天ci项目规划 前后台分离 1/31/2016 2:40:26 PM 前后台 表面上看前后台不同网站 但是数据是他们之间的联系要完成结构完整项目 设计好前后台 基于mvc框架 前后台那些地方不同 ...

  3. js排序算法总结——冒泡,快速,选择,插入,希尔,归并

    相信排序是任何一个程序猿都会用到的东西,今天简单总结记录下常见的排序算法. 一.冒泡排序 说起冒泡排序,可能每个人都不会陌生,实现思路相当简单明了,就是不停的对数组进行两两比较,将较大(较小)的一项放 ...

  4. HTTP 使用期及新鲜度算法

    使用期算法: /* * age_value 当代理服务器用自己的头部去响应请求时,Age标明实体产生到现在多长时间了. * date_value HTTP 服务器应答中的Date字段 原始服务器 * ...

  5. excel使用总结

    单元格拆分:选中列-->数据-->分列 常用函数: clean 清除文本中不能打印的字符 countif,countifs,在指定区域中按指定条件对单元格进行计数(单条件计数,多条件计数) ...

  6. Bug管理系统 BugFree

    BugFree - 借鉴微软公司软件研发理念.免费且开放源代码.基于Web的精简版Bug管理系统 在线演示:http://www.bugfree.org.cn/demo/Login.php 其它项目管 ...

  7. js中this的用法

    经过近几周的模拟面试题,我查询了一些资料,今天就来说说,在js中this的用法吧.方法有四:第一,用作全局变量,第二,用作表该对象,第三,用作构造函数,第四,用作call和applay

  8. 不能链接云服务器mysql

    如果报host'' 不允许连接MySQL服务器  1130 错误的话如果你的3306端口打开了,也把user 里的host改为% 还是不行的话,请记得更改 站点域名设置,和你服务器相同,端口一致.

  9. Web系统的常用测试方法

    在51上看到一篇不错的文章,拿过来分享一下,学习学习! Web系统的常用测试方法如下: 1. 页面链接检查:每一个链接是否都有对应的页面,并且页面之间切换正确. 2. 相关性检查:删除/增加一项会不会 ...

  10. UML类图的6大关系

    <小酌重构系列>已经完成了大约1/3了,在这些文章中,我使用了一些简单的类图来描述重构策略.在之后的文章中,我可能会借助稍微复杂一些的UML类图来介绍.但是在此之前,我觉得有必要先介绍一下 ...