【Win 10应用开发】多窗口视图

摘要:
WindowsApp一般情况下,同一时刻只能有一个应用程序实例在运行,为了在特殊需求下可以同时呈现不同的UI,SDK提供了多视图操作支持。CoreApplication类负责创建视图,调用CreateNewView方法可以创建一个新的视图,创建后以CoreApplicationView对象返回。已创建的视图在CoreApplication.Views列表中,在应用程序运行期间,所有被创建的视图都在这个列表中,所以,还是节约一下资源,不要乱创建视图。一种方法是在Dispatcher插入的代码中访问ApplicationView.GetApplicationViewIdForWindow方法,它可以从新视图所属的窗口中获取到视图ID。

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);
            //初始化视图
            //注意,必须在对应的线程上执行
            awaitnewView.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 asucDisplayPage;
                    if (uc == null)
                    {
                        uc = newucDisplayPage();
                        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 = awaitApplicationViewSwitcher.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方法中一样。

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

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

【Win 10应用开发】多窗口视图第1张

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

免责声明:文章转载自《【Win 10应用开发】多窗口视图》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇openresty使用笔记(一)VNware上安装虚拟机Ubuntu16.10 并安装petalinux(版本问题的坑 弃帖 另开一帖)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

ios 多线程

转自:http://www.maxiaoguo.com/clothes/254.html 多线程包含:GCD  NSOperation   NSOperation是在GCD语言的基础上开发的,GCD类C语言, NSOperation OC语法 GCD: 名词解释  并行 dispatch_queue_t q = dispatch_queue_crea...

C# 线程手册 第二章 .NET 中的线程 终止/等待线程

Abort()方法可以用来终止当前线程。不论何种情况下你想终止线程,比如线程执行了太长时间或者用户取消了之前的决定,Abort()方法都很重要。在一个花费很长时间的搜索进程中你可能想使用这个方法。一个搜索引擎可能在继续运行但是用户已经看到了他们想要的结果,所以用户会终止搜索引擎所运行的线程。当在一个线程外调用Abort()方法时,会引发一个ThreadAb...

Qt 学习之路 2(75):线程总结

前面我们已经详细介绍过有关线程的一些值得注意的事项。现在我们开始对线程做一些总结。 有关线程,你可以做的是: 在QThread子类添加信号。这是绝对安全的,并且也是正确的(前面我们已经详细介绍过,发送者的线程依附性没有关系) 不应该做的是: 调用moveToThread(this)函数 指定连接类型:这通常意味着你正在做错误的事情,比如将QThread控...

Java面试——多线程面试题总结

0.前言 在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分,本文汇总了常见的一些多线程面试题。 一些问题,比如volatile关键词的作用,synchronized和ReentrantLock的区别,wait()和sleep()的区别等等问题,已经在之前写过的文章中提到过了,这里就不赘述了,有兴趣可以查看以下几篇文章:Java并发——线程同...

java面试宝典

相关概念 面向对象的三个特征 封装,继承,多态.这个应该是人人皆知.有时候也会加上抽象. 多态的好处 允许不同类对象对同一消息做出响应,即同一消息可以根据发送对象的不同而采用多种不同的行为方式(发送消息就是函数调用).主要有以下优点: 可替换性:多态对已存在代码具有可替换性. 可扩充性:增加新的子类不影响已经存在的类结构. 接口性:多态是超累通过方法签名...

web 阶段的一些简答题

1.jsp 9个隐含对象 2. jsp 4大域对象 3.mybatis 中 #{} %{ } 的区别于联系 4. Servlet容器默认是采用单实例多线程的方式处理多个请求的: 5.Cookie 与Session 的异同 6. 请描述对web 服务器的理解(Tomcat),请列举出tomcat7下的目录以及各个目录的作用 7. 请描述 servlet与st...