【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 > 1)
            {
                newView = CoreApplication.Views[1];
            }
            // 如果没有这个视图,就创一个
            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

时间: 2024-08-06 16:06:46

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

【Win 10应用开发】实现全屏播放的方法

原文:[Win 10应用开发]实现全屏播放的方法 有人会问,以前的MediaElement控件不是有现成的一排操作按钮吗?而且可以直接进入全屏播放.是的,我们知道,以往的Store App都是在全屏模式下运行的,只要MediaElement控件填满整个窗口,就等于全屏播放了,但是,Win10应用是窗口化的,将MediaElement控件的IsFullWindow属性设置为true后,就会这样: 从上面的截图看,MediaElement控件只是覆盖整个窗口而已,并没有实现全屏.那有办法让它全屏播放

【Win 10应用开发】如何知道当前APP在哪个平台设备上运行

[Win 10应用开发]如何知道当前APP在哪个平台设备上运行 在做Win10开发的时候,我们可能经常会需要获得当前程序在在哪个平台设备上运行,用于UI和相关API的调用,那么可以通过什么方式知道当前APP运行的平台呢? 今天这里提供两个方法给大家做参考: 方法一:DeviceFamily 通过Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily,来获取当前的平台设备,目前只可以得到两个值Windows.Mobile或Wind

【Win 10 应用开发】打印UI元素

原文:[Win 10 应用开发]打印UI元素 Windows App支持将UI界面进行打印的功能,这与浏览器中的打印网页的用途相近,其好处就是“所见即所得”,直接把界面上呈现的内容打印下来,比重新创建打印图像方便得多. 要在通用App中实现打印,主要依靠以下几个类型: PrintManager:位于Windows.Graphics.Printing命名空间,主要负责显示打印对话框,设置打印源等操作.在使用时,首先调用GetForCurrentView静态方法得到一个PrintManager实例:

【Win 10应用开发】如何知道UAP在哪个平台上运行

原文:[Win 10应用开发]如何知道UAP在哪个平台上运行 面向22世纪的现代化应用程序可以同时在多种设备上运行,于是有朋友会有一个疑问:有时候,我们还真的需要判断一下,UAP应用程序在哪个平台上运行.尽管大多情况下我们不必要这样做,但某些特殊情况还得考虑.比如一串数据列表,我希望如果在桌面上运行时就以横向列表展现:但要是运行在手机上就以纵向列表展现. 也就是说,其实我们只需分析两种情况即可: 一.桌面.(台式机.笔记本.平板.游戏机.发广告专用机.导航器……) 二.移动环境.其实就是手机.

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

原文:[Win 10 应用开发]RTM版的UAP项目解剖 Windows 10 发布后,其实SDK也偷偷地在VS的自定义安装列表中出现了,今天开发人员中心也更新了下载.正式版的SDK在API结构上和以前预览的时候是一样的,只是版本变成10240罢了,所以大家不要问老周有什么新的API. API虽然没变,但VS中的应用程序项目是有了新变化.毕竟以前都是预览的,而现在是“正规军”,以前练兵时都用土豆枪,现在都是真刀真枪干了,故而应用程序项目是有变化的. 以前老周跟大家讲的修改项目模板,去掉遥测类库的

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

原文:[Win 10 应用开发]Toast通知激活应用--前台&后台 老周最近热衷于讲故事,接下来还是讲故事时间. 有人问我:你上大学的时候,有加入过学生会吗?读大学有没有必要加入学生会? 哎哟,这怎么回答呢,从短期来说,加入学生会有点用,至少可以娱乐一下,运气好的话,说不定能遇到红颜知己,但这概率相当低.从长远发展看嘛,是没什么用.老周当年读了四年本科,在学生会混了四年,什么名堂也没混出来. 一方面老周向来不求虚名,所以也没去参选所谓的什么部长.主席之类的,这些“官衔”听起来很高大上,实际上很

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

这个功能其实并不常用,一般开发较少涉及到证书,不过,简单了解一下还是有必要的. 先来说说制作测试证书的方法,这里老周讲两种方法,可以生成用于测试的.pfx文件. 产生证书,大家都知道有个makecert工具.好,我们先用这个工具来生成一个证书,并存放到当前用户的证书存储中.打开VS的开发人员命令提示符,然后输入: makecert -n "CN=中国好男人" -pe -sr CurrentUser -ss My -b 01/01/2016 -e 12/31/2018 -n 表示证书的标

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

在若干天之前,老周给大家讲了Adaptive Toast通知的XML模板,所以相应地,今天老周给大家介绍一下Adaptive磁贴的新XML模板. 同样道理,你依旧可以使用8.1时候的磁贴模板,在win 10的API中也是支持的,此外,Win10 App还支持全新的自适应磁贴模板,本文老周就给大家先讲一下基本结构,下一篇文章中咱们再说一说复杂排版. 应用程序的图标可以分为两类:第一类是应用商店上专用的,就是你的应用提交到商店后,给用户看的图标:另一类就是应用本身的一些图标或磁贴. 磁贴其实也就这么

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

这个功能必须在“红石-1”(build 14393)以上的系统版中才能使用,运行在一台设备上的应用,可以通过URI来启动另一台设备上的应用.激活远程应用需要以下前提: 系统必须是build 14393或以上版本,UWP应用必须使用14393或以上版本的SDK开发. 被启动的应用应当支持协议激活,比如Cortana的协议URI为:[ms-cortana:],当然如果是你自己开发的应用,可以自己定义一个协议,名字随便取,不要跟系统的协议或别人的应用冲突就行,比如:[haha:][zxzx:]等. 必

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

延迟共享是啥呢,这么说吧,就是在应用程序打开共享面板选择共享目标时,不会设置要共享的数据,而是等到共享目标请求数据时,才会发送数据,而且,延迟操作可以在后台进行. 这样说似乎过于抽象,最好的诠释方法,还是通过实例对比来观察吧. 老周设计的示例解决方案包含三个项目,其中一个是共享目标,用来接收共享的文本内容,并把文本写入到一个.txt文件中,存放到“文档”库中. 另外两个项目是:一个是未延迟的共享行为,再一个是延迟共享行为. 下面来对比一下效果. 先看未延迟共享的操作,如下图. 因为我在发送数据前