【WPF学习】第二十六章 Application类——应用程序的生命周期
在WPF中,应用程序会经历简单的生命周期。在应用程序启动后,将立即创建应用程序对象,在应用程序运行时触发各种应用程序事件,你可以选择监视其中的某些事件。最后,当释放应用程序对象时,应用程序将结束。
一、创建Application对象
使用Application类的最简单方式是手动创建它。下面的示例演示了最小的程序:在应用程序入口(Main()方法)处创建名为MainWindow的窗口,并启动一个新的应用程序:
在本质上,Visual Studio为Application类使用的模型与用于窗口的模型相同。起点是XAML模板,默认情况下该模板被命名为App.xaml,它看起来如下所示:
<Application x:Class="TestApplication.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
</Application>
在“【WPF学习】第四章 加载和编译XAML”介绍过,在XAML中使用Class特性创建派生自元素的类。因此,该类创建派生自Application的类,类名为TestApplication.App(TestApplication是项目名称,也是在其中定义类的名称空间,App是Visual Studio为派生自Application的自定义类使用的名称。如果愿意,可将类名该为任何更有趣的内容)。
Application标签不仅创建自定义的应用程序类,还设置StartupUri属性来确定代表主窗口的XAML文档。因此,不需要时候用代码显示地实例化这个窗口——XAML解析器将自动完成这项工作。
与窗口一样,应用程序类也在两个独立部分中进行定义,在编译时融合到一起。自动生成的部分在项目中是不可见的,但该部分包含Main()入口出以启动应用程序的代码。该部分看起来如下所示:
public class App:Application
{
[STAThread]
public static void Main()
{
Program app = new Program();
app.MainWindow = new MainWindow("MainWindow.xaml");
app.MainWindow.ShowDialog();
}
}
如果确实对查看XAMl模板创建的自定义应用程序类感兴趣,可查找位于项目目录中的obj\Debug文件夹中的App.g.cs文件。
这里给出的自动生成的代码和手工编写的自定义应用程序类代码之间唯一的区别是,自动生成的类使用StartupUri属性,而不是设置MainWindow属性或把住窗体作为参数传递给Run()方法。只要使用相同的URI格式,就可以自由地使用这种方法创建自定义应用程序类。需要创建相对Uri对象,用于命名项目中的XAML文档(该XAML文档是编译过的,并作为BAML资源被嵌入到应用程序的程序集中。该资源的名称就是原来XAML文件的名称。在上面的示例中,应用程序包含名为MainWindow.xaml的资源,该资源包含以编译过的XAML文档)。
自定义应用程序类的第二部分存储在项目中诸如App.xaml.cs的文件中。该部分包含开发人员添加的处理事件的代码,最初是空的:
public partial class App : Application
{
}
这个文件通过部分类技术和自动生成的应用程序代码融合到一起。
三、应用程序的关闭方式
通常,只要还有窗口尚未关闭,Application类就保持应用程序处于有效状态。如果这不是期望的行为,可调整Application.ShutdownMode属性。如果手动实例化Application对象,就需要在调用Run()方法之前设置ShutdownMode属性。如果使用App.xaml文件,那么可在XAML文件中简单设置ShutdownMode属性。
对于关闭模式有三种选择,如下表所示:
表 ShutdownMode枚举值
例如,如果希望使用OnMainWindowClose方式,并且正在使用App.xaml文件,那么需要添加如下内容:
<Application x:Class="TestApplication.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml" ShutdownMode="OnMainWindowClose">
</Application>
不管选择哪种关闭方法,总是可以使用Application.Shutdown()方法立即终止应用程序(当然,当调用Shutdown()方法时,应用程序未必立刻停止运行。调用Application.Shutdown()方法会导致Application.Run()方法立即返回,但仍可继续运行Main()方法中的其他带代码或者响应Application.Exit事件)。
四、应用程序事件
最初,App.xaml.cs文件不包含任何代码。尽管不需要代码,但可添加代码来处理应用程序事件。Application类提供了为数不多的非常有用的事件。下表给出了其中重要的几个。
表 应用程序事件
处理事件时有两种选择:关联事件处理程序或重写相应的受保护方法。如果选择处理应用程序事件,不需要使用委托代码来关联事件处理程序,而是可以使用App.xaml文件中的某个特性来关联事件处理程序。例如,如果有如下事件处理程序:
private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
MessageBox.Show("An unhandled " + e.Exception.GetType().ToString() +
" exception was caught and ignored.");
e.Handled = true;
}
可使用下面的XAML来连接上面的事件处理程序:
<Application x:Class="TestApplication.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml" ShutdownMode="OnMainWindowClose" DispatcherUnhandledException="Application_DispatcherUnhandledException">
<Application.Resources> </Application.Resources>
</Application>
对于每个应用程序事件,可调用相应的方法来引发该事件。这个方法的名称就是事件的名称,只要在前面加上前缀On,因此Startup变成了OnStartup(),Exit变成OnExit(),等等。这种方式在.NET中是十分常见的。唯一的例外是DispatcherExceptionUnhandled事件——该事件没有相应的OnDispatcherExceptionUnhandled()方法,所以始终需要使用事件处理程序。
下面是一个自定义的应用程序类,它重写了OnSessionEnding()方法, 并且如未设置了相应的标志,该方法会阻止关闭系统和应用程序自身:
public partial class App : Application
{ private bool unsavedData = false;
public bool UnSavedData
{
get { return unsavedData; }
set { unsavedData = value; }
}
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
unsavedData = true;
} protected override void OnSessionEnding(SessionEndingCancelEventArgs e)
{
base.OnSessionEnding(e);
if (unsavedData)
{
e.Cancel = true;
MessageBox.Show(
"The application attempted to be closed as a result of " +
e.ReasonSessionEnding.ToString() +
".This is not allowed,as you have unsaved data.");
}
}
}
当重写应用程序方法时,最好首先调用基类的实现。通常,基类的实现知识引发相应的应用程序事件。
显然,实现这一技术的更精妙的方法是,不使用消息框,而应显示几个确认对话框,让用户选择是继续(退出应用程序和Window系统)还是取消关闭。
【WPF学习】第二十六章 Application类——应用程序的生命周期的更多相关文章
- UNP学习笔记(第二十六章 线程)
线程有时称为轻权进程(lightweight process) 同一进程内的所有线程共享相同的全局内存.这使得线程之间易于共享信息,然后这样也会带来同步的问题 同一进程内的所有线程处理共享全局变量外还 ...
- Gradle 1.12用户指南翻译——第二十六章. War 插件
其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://g ...
- “全栈2019”Java多线程第二十六章:同步方法生产者与消费者线程
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- “全栈2019”Java第三十六章:类
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java第二十六章:流程控制语句中循环语句do-while
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- 风炫安全WEB安全学习第二十六节课 XSS常见绕过防御技巧
风炫安全WEB安全学习第二十六节课 XSS常见绕过防御技巧 XSS绕过-过滤-编码 核心思想 后台过滤了特殊字符,比如说
- SpringBoot | 第二十六章:邮件发送
前言 讲解了日志相关的知识点后.今天来点相对简单的,一般上,我们在开发一些注册功能.发送验证码或者订单服务时,都会通过短信或者邮件的方式通知消费者,注册或者订单的相关信息.而且基本上邮件的内容都是模版 ...
- Android 4学习(5):概述 - Android应用程序的生命周期
参考:<Professional Android 4 Application Development> Android应用程序生命周期 Android应用程序无法控制自己的生命周期,因此它 ...
- WP8.1学习系列(第二十六章)——控件模板
在本文中 自定义控件模板示例 指定控件的可视结构. 指定控件的可视行为 使用工具轻松处理主题 控件和辅助功能 了解有关控件默认模板的详细信息 控件模板中的主题资源 相关主题 在 XAML 框架中,如果 ...
随机推荐
- 用ubuntu里的vim搭建一个apache2+php+mysql环境一路踩的坑
先是安装apache2,这个很顺利,一个apt install apache就搞定了. (PS:查看linux是否已经安装了apache服务,可以通过执行apachectl -v,如果安装了的话会显示 ...
- asdf
[root@host01 ~]# netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' TIME_WAIT 3 CL ...
- Asp.NetCore3.1版本的CodeFirst与经典的三层架构与AutoFac批量注入
Core3.1 CodeFirst与AutoFac批量注入(最下面附GitHub完整 Demo,由于上传网速较慢,这里就直接压缩打包上传了) ===Core3.1 CodeFirst 数据库为远程阿里 ...
- 洛谷$P3647\ [APIO2014]$连珠线 换根$dp$
正解:换根$dp$ 解题报告: 传送门! 谁能想到$9102$年了$gql$居然还没写过换根$dp$呢,,,$/kel$ 考虑固定了从哪个点开始之后,以这个点作为根,蓝线只可能是直上直下的,形如&qu ...
- asp.net core 3.x 通用主机原理及使用
一.前言 只是讲asp.net core 3.x通用主机的大致原理,这些东西是通过查看源码以及自己根据经验总结得来的,在文章中不会深入源码,因为个人觉得懂原理就晓得扩展点,后期碰到有需求的时候再仔细去 ...
- Kubernetes资源与对象简述
资料 k8s基本对象概念 背景 资源和对象 Kubernetes 中的所有内容都被抽象为"资源",如 Pod.Service.Node 等都是资源."对象" ...
- 2019HDU多校第四场题解
1001.AND Minimum Spanning Tree 传送门:HDU6614 题意:给你一个又n个点的完全图,点编号从1~n,每条边的权值为被连接的两点编号按位与后的值.现在要你找到最小生成树 ...
- Essential C++学习笔记
1.当我们调用一个函数时,会在内存中建立起一块特殊区域,称为“程序栈”,这块特殊区域提供了每个函数参数的存储空间,它也提供函数所定义的每个对象的内存空间--我们将这些对象称为局部对象.一旦函数完成,这 ...
- 使用redis的zset实现高效分页查询(附完整代码)
一.需求 移动端系统里有用户和文章,文章可设置权限对部分用户开放.现要实现的功能是,用户浏览自己能看的最新文章,并可以上滑分页查看. 二.数据库表设计 涉及到的数据库表有:用户表TbUser.文章表T ...
- win + ubuntu 双系统 grub引导项修复
ubuntu liveCD模式,找到ubuntu的系统盘位置,挂载到系统上面,然后使用grub进行修复 ubuntu liveCD模式下是用boot-repair软件进行修复 grub急救模式 1. ...