WPF中文网

App.xaml与Application类

事实上,xaml类型的文件包含两部分,一部分以.xaml扩展名结尾的前端代码,另一部分以.xaml.cs结尾的后端代码,通常我们也把后端代码称为隐藏代码。

我们来看看App.xaml的前端代码和后端代码分别是什么。

前端代码的全称为Extensible Application Markup Language,简称XAML。

//前端代码
<Application x:Class="HelloWorld.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:HelloWorld"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
         
    </Application.Resources>
</Application>
//后端代码
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;

namespace HelloWorld
{
    /// <summary>
    /// App.xaml 的交互逻辑
    /// </summary>
    public partial class App : Application
    {
    }
}

我们先从比较熟悉的后端代码开始分析。WPF的后端代码可以是C#或VB两种语言,本教程一律采用C#语言进行演示。从上面的源代码可以看出,这里定义了一个名叫App的类型,且修饰符为partial关键字,标明App是一个局部类型。最后,App将继承Application父类。

Partial有什么作用?

在C#中,使用 partial 关键字可以将一个类、结构体、接口或者方法分为多个部分进行声明,这些部分可以分布在同一个源文件中,也可以分布在不同的文件中。意思就是说,这里的App类型被分别定义在前端xaml和后端的cs文件中,就好比是一对夫妻,xaml主外,cs主内,两者合二为一,才能形成一个完整的App类型。

那么,前段是如何定义一个类型的呢?

在xaml代码中,我们可以看到有一个<Application>的标签,同时在里面还有一句话:x:Class="HelloWorld.App",它定义一个名叫App的类型,这个类型位于命令空间HelloWorld之中,与后端代码的namespace HelloWorld保持一致。我们可以将x:Class和c#里面的class关键词看成是同一个东西,都表示定义某个类型。

既然前端代码和后端代码都继承了Application父类,那么,这个Application类到底是个什么东西?

namespace System.Windows
{
    //
    // 摘要:
    //     封装 Windows Presentation Foundation (WPF) 应用程序。
    public class Application : DispatcherObject, IHaveResources, IQueryAmbient
    {
        [SecurityCritical]
        public Application();
        //获取或设置 System.Reflection.Assembly 提供包 统一资源标识符 (URI) 中的资源 WPF 应用程序。        
        public static Assembly ResourceAssembly { get; set; }

        //获取 System.Windows.Application 当前对象 System.AppDomain。
        public static Application Current { get; }

        //获取应用程序中实例化的窗口。
        public WindowCollection Windows { get; }

        //获取或设置该应用程序的主窗口。
        public Window MainWindow { get; set; }

        //获取或设置导致的情况, System.Windows.Application.Shutdown 来调用方法。
        public ShutdownMode ShutdownMode { get; set; }

        //获取或设置应用程序范围的资源,如样式和画笔的集合。
        [Ambient]
        public ResourceDictionary Resources { get; set; }

        //获取或设置 UI 一个应用程序启动时自动显示。
        public Uri StartupUri { get; set; }

        //获取应用程序作用域属性的集合。
        public IDictionary Properties { get; }

        
        public event EventHandler Deactivated;
        public event SessionEndingCancelEventHandler SessionEnding;
        public event DispatcherUnhandledExceptionEventHandler DispatcherUnhandledException;
        public event NavigatingCancelEventHandler Navigating;
        public event NavigatedEventHandler Navigated;
        public event NavigationProgressEventHandler NavigationProgress;
        public event NavigationFailedEventHandler NavigationFailed;
        public event LoadCompletedEventHandler LoadCompleted;
        public event EventHandler Activated;
        public event NavigationStoppedEventHandler NavigationStopped;
        public event FragmentNavigationEventHandler FragmentNavigation;

        public static StreamResourceInfo GetContentStream(Uri uriContent);
        public static string GetCookie(Uri uri);
        public static StreamResourceInfo GetRemoteStream(Uri uriRemote);
        public static StreamResourceInfo GetResourceStream(Uri uriResource);
        public static object LoadComponent(Uri resourceLocator);
        public static void LoadComponent(object component, Uri resourceLocator);
        public static void SetCookie(Uri uri, string value);
        public object FindResource(object resourceKey);
        public int Run(Window window);
        public int Run();
        public void Shutdown();
        public void Shutdown(int exitCode);
        public object TryFindResource(object resourceKey);
        protected virtual void OnActivated(EventArgs e);
        protected virtual void OnDeactivated(EventArgs e);
        protected virtual void OnExit(ExitEventArgs e);
        protected virtual void OnFragmentNavigation(FragmentNavigationEventArgs e);
        protected virtual void OnLoadCompleted(NavigationEventArgs e);
        protected virtual void OnNavigated(NavigationEventArgs e);
        protected virtual void OnNavigating(NavigatingCancelEventArgs e);
        protected virtual void OnNavigationFailed(NavigationFailedEventArgs e);
        protected virtual void OnNavigationProgress(NavigationProgressEventArgs e);
        protected virtual void OnNavigationStopped(NavigationEventArgs e);
        protected virtual void OnSessionEnding(SessionEndingCancelEventArgs e);
        protected virtual void OnStartup(StartupEventArgs e);

    }
}

Application类继承于DispatcherObject父类,我们曾在《WPF概述》一文中提到,DispatcherObject是WPF的最终抽象基类,下文我们将从这个最终抽象基类说起。在这里我们先讨论一下Application类。

Application类拥有一些属性、事件、和方法,与过去在C#学习中碰到的其它类型从结构上没什么不同。摘要显示,Application类是封装 Windows Presentation Foundation (WPF) 的应用程序。我们开发一款WPF应用程序,本质上是去继承了这个类,并创建了一些窗体和对话框,通过C#语言编写一系列的业务逻辑实现,最终编译成软件交付给用户。

捡几个比较重要的成员了解一下Application类吧!

一个应用程序就好比是一套房子,大多数情况下,这套房子拥有客厅、主卧、客卧、厨房、厕所、阳台等地方,而应用程序会包括多个窗体、对话框等界面,这些窗体和对话框就是这些不同的房间;在众多的窗体中,会有一个主窗体,也就是Application类的MainWindow属性,MainWindow就像是房子的客厅,因为我们推开门进去,通常映入眼帘的就是客厅。但是类似QQ软件呢,打开后并不是立即进入到主窗体,而是登录窗体,只有通过权限验证后才会进入主窗体。

那么,如何在启动程序时决定先显示哪个窗体呢?答案是Application类的StartupUri 属性。StartupUri属性是Uri类型,即统一资源标识符 (URI),它可以指定应用程序第一次启动时显示的用户界面 (UI)。当然,它的功能还远远不止这个,关于URI,我们会专门拿一节内容探讨。

再对比一下QQ和微信两款软件,虽然都有登录窗体和主窗体,都能实现文字和语音信息交换,但是它们的界面截然不同,如何在WPF应用程序中设计出不同风格的界面?

答案是,我们只需要将这些设计要素(资源)放在Application的Resources属性中即可。换句话,我们希望窗体的背景颜色、字体大小、对各种控件所设计的模板样式等内容,全部都只需要放到Resources属性中,这样整个应用都会从Resources中去获取我们提供的资源,并最终呈现出我们想要的样子。

最后我想说的是,有诞生就会有消亡。就像秦始皇的阿房宫,从开始创建、到使用、被销毁,到最后只存在于人们的记忆中,阿房宫走完了它的一生;而一个应用程序,也会有它自己的生命周期,从它在计算机内存中诞生、诞生的过程、用户的使用过程、从内存中消失(退出),同样也会有一个生命过程,那么这个过程是怎么样的呢?

下一节,我们来讨论一下Application的生命周期。

——重庆教主 2023年8月10日

copyright @重庆教主 WPF中文网 联系站长:(QQ)23611316 (微信)movieclip (QQ群).NET小白课堂:864486030 | 本文由WPF中文网原创发布,谢绝转载 渝ICP备2023009518号-1