WinRT提供了Windows.ApplicationModel.Core.CoreApplication类,其定义如下: public static class CoreApplication { // 返回与主调线程关联的CoreApplicationView对象 public static CoreApplicationView GetCurrentView(); // 返回该进程内所有已存在的CoreApplicationViews对象 public static IReadOnlyList<CoreApplicationView> Views { get; } // 返回主视图线程的CoreApplicationView对象 public static CoreApplicationView MainView { get; } // 这些事件将在本章稍后进行讨论 public static event EventHandler<Object> Resuming; public static event EventHandler<SuspendingEventArgs> Suspending; // 这些事件仅用于调试 public static event EventHandler<Object> Exiting; public static event EventHandler<UnhandledErrorDetectedEventArgs> UnhandledErrorDetected; // 该方法允许你创建多个主视图窗口 public static CoreApplicationView CreateNewView(); // 一些成员未在这里展示…… }
可以看出,该类是一个静态类。这意味着我们将无法创建该类的实例。因此该静态类是从总体上对应用进行管理。然而,静态类无法利用一些良好的面向对象编程特性,如继承、虚方法等。因此,对于XAML开发人员,WinRT还提供了Windows.UI.Xaml.Application类(我们之前曾讨论过);我们所需的所有虚方法都位于该类中,以便我们实现自己的激活代码。实际上,我们所讨论的Application单例对象包装了静态类CoreApplication。接下来,笔者将向你展示Application类的一些其他成员:
public class Application { // 静态成员: public static void Start(ApplicationInitializationCallback callback); public static Application Current { get; } // 与由CoreApplication类提供的Resuming及Suspending事件相同 public event EventHandler<object> Resuming; public event SuspendingEventHandler Suspending; // XAML特有的属性和事件: public DebugSettings DebugSettings { get; } public ApplicationTheme RequestedTheme { get; set; } public ResourceDictionary Resources { get; set; } public event UnhandledExceptionEventHandler UnhandledException; // 之前介绍过的虚方法以及其他成员来在这里展示…… } 每个App类都由该Application类派生,继承其所有的实例成员,并允许开发人员对虚函数进行重载。 现在我们再来回顾CoreApplication类。该类的许多成员都可返回CoreApplicationView对象。CoreApplicationView类的定义如下: public sealed class CoreApplicationView { public CoreDispatcher Dispatcher { get; } public CoreWindow CoreWindow { get; } public Boolean IsMain { get; } public Boolean IsHosted { get; } public event TypedEventHandler<CoreApplicationView, IActivatedEventArgs> Activated; }
可见,CoreApplicationView对象引用了一个CoreDispatcher对象(分派窗口消息的消息泵)和一个CoreWindow对象(实际的绘图图面),并通过一个专门的域来指示这个CoreWindow对象是应用的主窗口还是该应用的宿主窗口。当该窗口被激活时,将引发Activated事件;IActivatedEventArgs接口中包含了一个Kind属性,用于返回ActivationKind枚举类型的值(如表3.1所示)。该接口的其他成员将在第3.4节中进行介绍。
CoreWindow对象是一个绘图图面(drawing surface),其中关联了窗口所应拥有的一切标准元素。它拥有一些状态(域)来指示边框矩形的属性、输入是否被启用、是否显示光标、窗口是否可见等。它还提供了一些事件(如Activated、Closed、SizeChanged、VisibilityChanged)和键盘及指针(鼠标、触摸及触笔)输入事件。此外,它还拥有一些方法,如Activate、Close、Get(Async)KeyState、Set/ReleasePointerCapture以及一个静态方法GetForCurrentThread。
对于XAML开发人员,还可使用密封类Windows.UI.Xaml.Window。该类对CoreWindows对象进行了简单的包装:
public sealed class Window { public static Window Current { get; } // 返回调用线程的窗口 public CoreWindow CoreWindow { get; } public CoreDispatcher Dispatcher { get; } // 与CoreApplicationView.Dispatcher相同 // 该Content属性表明XAML与窗口的绘图图面如何集成: public UIElement Content { get; set; } // 该类开放了一些相同的属性(Bounds, Visible) // 该类开放了一些相同的事件(Activated, Closed, SizeChanged, VisibilityChanged) // 该类开放了一些相同的方法(Activate, Close) } 本节最后介绍的WinRT类为Windows.UI.Core.CoreDispatcher,其定义如下: public sealed class CoreDispatcher { // 如果调用线程为与CoreDispatcher对象关联的同一个线程,则返回true public Boolean HasThreadAccess { get; } // 调用该方法使CoreDispatcher的线程以优先级Idle, Low, Normal, or High来执行agileCallback。 public IAsyncAction RunAsync( CoreDispatcherPriority priority, DispatchedHandler agileCallback); // 调用该方法以获取或设置调度程序当前正在执行的代码的优先级 public CoreDispatcherPriority CurrentPriority { get; set; } // 其他成员未进行展示…… }
许多.NET开发者都已对这个CoreDispatcher类非常熟悉,因为该类的行为与WPF和Silverlight中的Dispatcher类颇为相似。由于每个CoreApplicationView仅有一个线程对其进行管理,其CoreDispatcher对象使你可在同一个线程中执行某一方法,从而允许该方法对视图的用户界面进行更新。这对一些场合十分有用,比如当一些任意线程调用某一方法时,你需要对用户界面进行更新。笔者以后还将进一步介绍CoreDispatcher类,并在其他章节中演示如何使用该类。
Windows应用商店应用的主视图可创建一些额外的视图以显示额外的内容。这些视图可在同一显示器中并排显示或在不同显示器分别显示,用户还可依据自己的喜好对其尺寸进行调整。例如,Windows Mail应用允许你打开新视图,使你在撰写新邮件的同时参考另一封邮件。应用可通过调用CoreApplication类的静态方法CreateNewView来创建新的视图线程和视图。该方法会创建一个新线程,并连同其CoreDispatcher对象和CoreWindow对象一起创建,并最终返回一个CoreApplicationView对象。对于该CoreApplicationView对象,属性IsMain和IsHosted都将返回false。当然,在你创建新视图时,应用的OnWindowCreated虚方法将通过这个新线程被调用。然后,你便可利用下列代码为这个新视图创建用户界面:
private async Task CreateNewViewWindow() { // Windows创建新线程,CoreDispatcher, CoreWindow, 及CoreApplicationView对象 CoreApplicationView cav = CoreApplication.CreateNewView(); CoreWindow newAppViewWindow = null; // 该引用将指向新视图的窗口 // 用新线程初始化新视图的内容 await cav.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { // Give the new thread's window back to the creating thread newAppViewWindow = Window.Current.CoreWindow; // Create the desired UI element tree and make it the content of the new window Window.Current.Content = new MyPage(); Window.Current.Activate(); }); // 当新线程对其视图初始化完毕后,串讲线程将使其可见 Int32 newAppViewId = ApplicationView.GetApplicationViewIdForWindow(newAppViewWindow); await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newAppViewId, ViewSizePreference.UseLess); // SDK文档中关于Windows.UI.ViewManagement.ApplicationViewSwitcher的部分对 // 该类的其他方法进行了解释,以允许你对应用中视图的切换进行控制 } 上面的代码利用了Windows.UI.ViewManagement.Application类。该类提供了许多与视图相关的动态属性。换言之,这些属性的取值经常会发生变化。该类的定义如下: public sealed class ApplicationView { // 为调用线程获取当前视图 public static ApplicationView GetForCurrentView(); // 获取对应于某个特定CoreWindow的唯一窗口ID public static Int32 GetApplicationViewIdForWindow(ICoreWindow window); // 获取表示该视图的唯一ID;注意:该ID将被传给某个 // XxxActivatedEventArgs对象的 CurrentlyShownApplicationViewId属性 public Int32 Id { get; } // 获取或设置当前视图的标题(显示在任务切换程序中)以及截屏键是否可捕捉其内容 public String Title { get; set; } public Boolean IsScreenCaptureEnabled { get; set; } // 与视图的位置和尺寸相关的只读属性 public ApplicationViewOrientation Orientation { get; } // Landscape or Portrait public Boolean AdjacentToLeftDisplayEdge { get; } public Boolean AdjacentToRightDisplayEdge { get; } public Boolean IsFullScreen { get; } public Boolean IsOnLockScreen { get; } // 当视图从任务切换程序中移除时将引发该事件(当用户关闭视图) public event TypedEventHandler<ApplicationView, ApplicationViewConsolidatedEventArgs> Consolidated; // 表明当所有视图均关闭时,应用是否终止(默认为false) public static Boolean TerminateAppOnFinalViewClose { get; set; } }