WPF_07_Application


WPF程序都是由 System.Windows.Application 类表示的一个实例,该类跟踪所有窗口,决定何时关闭程序,并引发可执行初始化和清除操作的程序事件。

程序生命周期

本质上,Visual Studio为 Application类使用的模板和窗口模板相同,默认该模板命名为 App.xaml .


    
         
    

与窗口一样,应用程序类也在两个独立部分中定义,在编译时融合到一起。自动生成的代码部分在项目中不可见,看起来如下:

using System;
using System.Windows;

public partial class App : Application
{
    [STAThread()]
    public static void Main()
    {
        WindowDemo.App app = new WindowDemo.App();
        app.InitializeComponent();
        app.Run();
    }

    public void InitializeComponent()
    {
        // 自动生成的代码并没有使用 MainWindow 属性
        this.StartupUri = new Uri("MainWindow.xaml", System.UriKind.Relative);
    }
}

如果想查看 XAML 模板创建的代码,可查找 obj\Debug 文件夹里的 App.g.cs 文件。

第二部分代码存储在 App.xaml.cs 文件中,包含开发人员添加的处理事件的代码,最初是空的:

public partial class App : Application
{
    // 这部分代码 会和自动生成的代码融合到一起
}

关闭程序

一般,只要还有窗口没关闭,Application 类就保持程序处于有效状态,可通过 Application.ShutdownMode 属性来修改。

名称 说明
OnLastWindowClose 默认行为,如果关闭了主窗口,Application.MainWindow仍引用已关闭窗口对象
OnMainWindowClose 只要主窗口处于打开状态,程序就保持运行状态
OnExplicitShutdown 除非调用 Application.Shutdown() 方法,否则程序不会结束

当调用Shutdown() 方法时,Application对象在 Run() 方法返回前自动关闭其他所有窗口,然后方法返回。

应用程序事件

最初,App.xaml.cs 文件不包含任何代码,但可添加处理应用程序事件。

名称 说明
Startup 调用 Run() 方法之后,主窗口显示之前发生。可使用该事件检查命令行参数,还可创建和显示主窗体(而不是用 StartUri属性)
Exit 程序关闭,并在 Run() 即将返回之前发生,此时不能取消关闭,但可重新启动
SessionEnding 在Widnows对话结束时发生-比如注销或关闭计算机。可设置 SessionEndingEventArgs.Cancel=true来取消关闭,否则将调用 Shutdown()
Activated 激活窗口时发生
Deactivated 取消激活窗口时发生
DispatcherUnhandledException 未处理的异常

处理事件时有两种选择:关联事件处理程序或重写相应的受保护方法。

Application类的任务

当第一次启动程序时会有一些延迟,CLR需要初始化 .NET 环境,然后启动程序。

显示初始界面

WPF 提供了添加初始界面的方法:

  1. 为项目添加图形文件(通常是.bmp,.png或.jpg)
  2. Solution Explorer 中选择图像文件
  3. 将 Build Action 修改为 SplashScreen .

下次运行程序时,图像会立即显示屏幕中央,一旦准备好运行时环境,而且 Application_Startup 方法执行完毕,第一个窗口就将显示出来,这时初始界面会很快消失。

当添加初始界面时,WPF编译器会自动生成 App.g.cs 文件添加类似下面的代码:

SplashScreen splashScreen = new SplashScreen("splashScreenImage.png");

// ture 表示第一个窗体弹出后,自动关掉初始界面
splsahScreen.Show(true);

MyApplication.App app = new MyApplication.App();
app.InitializeComponent();
app.Run();

// 初始界面关闭

可以改变初始界面隐藏的速度。调用 SplashScreen.Show(false) ,当调用 SplashScreen.Close() 方法时隐藏,并可以提供 TimeSpan 表示经过过长时间淡出初始界面。

处理命令行参数

需要相应 Application.Startup 事件,命令行参数通过 StartupEventArgs.Args 属性作为字符串数组提供的。

private static void App_Startup(object sender, StartupEventArgs e)
{
    FileViewer win = new FileViewer();

    if(e.Agrs.Length > 0)
    {
        string file = e.Args[0];
        if(System.IO.File.Exists(file))
        {
            win.LoadFile(file);
        }
        else
        {
            win.Show();
        }
    }
}

程序集资源

程序集资源时为项目添加文件,从而 Visual Studio 可将其签入到编译过的应用程序的 EXE 或 DLL 文件中。程序集资源又称为 二进制资源 ,因为它们作为不透明的二进制数据被嵌入到已编译的程序集中。

每次编译程序时,XAML 文件都会转换为解析效率更高的 BAML 文件作为独立资源嵌入到程序集中。

添加资源

在项目中添加文件,并在 Properties 窗口中将其 Build Action 设置为 Resource 来添加自己的资源。WPF将它们和其他 BAML 资源合并到单独的流中。

检索资源

使用资源有多种方法,低级方法是检索封装数据的 StreamResourceInfo 对象:

Assembly assembly = Assembly.GetAssembly(this.GetType());
string resourceName = assembly.GetName().Name + ".g";
ResourceManager rm = new ResourceManager(resourceName, assembly);

using(ResourceSet set = rm.GetResourceSet(CultureInfo.CurrentCulture, true, ture))
{
    UnmanagedMemoryStream s;
    s = (UnmanagedMemoryStream) set.GetObject("image/winter.jpg", true);
}

WPF提供了几个专门使用资源的类,使用资源的名称访问资源:



pack URL

WPF 使用 pack URL寻址编译过的资源。上面使用图像的相对URL来引用资源等效于:
pack://application:,,,/Images/happy.jpg
pack URL语法来自 XPS 标准。三个逗号实际上是三个转义的斜杠,即 application:/// .

还可以检索嵌入到另一个库中的资源,语法如下:




本地化

本地化程序的挑战在于整个工作过程-如何从项目中提取XAML文件,如何本地化这些XAML文件,如何将它们编译进附属程序集中,如何在应用中使用本地化的资源。

让项目支持本地化

在项目的 .csproj 文件中第一个 PropertyGroup 元素的任意地方添加以下元素:

en-US

编译程序时,会生成名为 en-US 的子文件夹,里面包含 附属程序集 ,与应用程序同名,扩展名为 .resources.dll .附属程序集包含了程序的所有编译过的 BAML 资源,以前这些资源保存在主应用程序的程序集中。

我的公众号

HelloProgram

WPF