【Win 10应用开发】多窗口视图
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应用开发】多窗口视图的更多相关文章
- 【Win 10 应用开发】启动远程设备上的应用
这个功能必须在“红石-1”(build 14393)以上的系统版中才能使用,运行在一台设备上的应用,可以通过URI来启动另一台设备上的应用.激活远程应用需要以下前提: 系统必须是build 14393 ...
- 【Win 10 应用开发】导入.pfx证书
这个功能其实并不常用,一般开发较少涉及到证书,不过,简单了解一下还是有必要的. 先来说说制作测试证书的方法,这里老周讲两种方法,可以生成用于测试的.pfx文件. 产生证书,大家都知道有个makecer ...
- 【Win 10应用开发】Adaptive磁贴模板的XML文档结构
在若干天之前,老周给大家讲了Adaptive Toast通知的XML模板,所以相应地,今天老周给大家介绍一下Adaptive磁贴的新XML模板. 同样道理,你依旧可以使用8.1时候的磁贴模板,在win ...
- 【Win 10应用开发】认识一下UAP项目
Windows 10 SDK预览版需要10030以上版本号的Win 10预览版系统才能使用.之前我安装的9926的系统,然后安装VS 2015 CTP 6,再装Win 10 SDK,但是在新建项目后, ...
- 【Win 10 应用开发】RTM版的UAP项目解剖
Windows 10 发布后,其实SDK也偷偷地在VS的自定义安装列表中出现了,今天开发人员中心也更新了下载.正式版的SDK在API结构上和以前预览的时候是一样的,只是版本变成10240罢了,所以大家 ...
- 【Win 10 应用开发】在代码中加载文本资源
记得前一次,老周给大伙,不,小伙伴们介绍了如何填写 .resw 文件,并且在 XAML 中使用 x:Uid 标记来加载.也顺便给大伙儿分析了运行时是如何解析 .resw 文件的. 本来说好了,后续老周 ...
- 【Win 10应用开发】延迟共享
延迟共享是啥呢,这么说吧,就是在应用程序打开共享面板选择共享目标时,不会设置要共享的数据,而是等到共享目标请求数据时,才会发送数据,而且,延迟操作可以在后台进行. 这样说似乎过于抽象,最好的诠释方法, ...
- 【Win 10 应用开发】Toast通知激活应用——前台&后台
老周最近热衷于讲故事,接下来还是讲故事时间. 有人问我:你上大学的时候,有加入过学生会吗?读大学有没有必要加入学生会? 哎哟,这怎么回答呢,从短期来说,加入学生会有点用,至少可以娱乐一下,运气好的话, ...
- 【Win 10 应用开发】UI Composition 札记(一):视图框架的实现
在开始今天的内容之前,老周先说一个问题,这个问题记得以前有人提过的. 设置 Windows.ApplicationModel.Core.CoreApplicationView.TitleBar.Ext ...
随机推荐
- acm入门 杭电1001题 有关溢出的考虑
最近在尝试做acm试题,刚刚是1001题就把我困住了,这是题目: Problem Description In this problem, your task is to calculate SUM( ...
- FileReader获取文件的base64编码
<input type="file" id="picFile" /> function readFile() { var obj = documen ...
- bzoj1001最小割
听说最大流过不去??? dinic果然神了,1000,000的点都能过(主要是比较稀疏) #include <cstdio> #define INF 9223372036854775807 ...
- 使用C#在CEF中拦截并响应请求
一.前言 忙里偷闲,研究了一下如何在CEF中拦截请求,并作出响应.这个功能对某些需要修改服务器响应的需求来说必不可少,可以直接读取本地文件作为响应内容. C#的CEF封装项目有很多,我使用的是Chro ...
- 还原后缀名为.bak的数据库备份文件
1.打开SQL Server Management Studio,随便右击击一个数据库选择任务-->还原-->数据库 4.在弹出来的窗口中的源选项中选择设备-->点选择设备--> ...
- c# Repeater中CommandArgument传多个参数
<ItemTemplate> <div onmouseover="javascript:this.style.cursor='hand ...
- android copy项目后修改项目名
有个eclipse下的Android项目,现在因为有个需求想在复制出来一个项目,把这个项目变成两个独立项目.在同一个工作空间下不能同时存在项目名称一样的项目,所以需要修改项目名.具体操作如下: 1.修 ...
- Go 语言的基本数据类型
Go 语言的基本数据类型 0)变量声明 var 变量名字 类型 = 表达式 例: 其中“类型”或“= 表达式”两个部分可以省略其中的一个. 1)根据初始化表达式来推导类型信息 2)默认值初始化为0. ...
- 最简单的android自定义进度条样式
一.自定义圆形进度条样式 1.在安卓项目drawable目录下新建一个xml文件如下:<?xml version="1.0" encoding="utf-8&quo ...
- ubuntu的vim模式
之前想修改一个文件的内容,居然发现之前的东西又随着时间在空气中淡忘了,所以取了网上的一些摘文. 1.vim #在命令行中输入vim,进入vim编辑器 2. i #按一下i键,下端显示 --INSERT ...