第二章主要是讲述了 App.xaml 和 App.xaml.cs文件。这两个文件决定了应用程序全局行为和操作,并且通过这两个文件将定义和行为代码分离。本文介绍了这两个文件的使用方式。
一.Application介绍
WPF和WinForm 很相似, WPF与WinForm一样有一个 Application对象来进行一些全局的行为和操作,并且每个 Domain (应用程序域)中仅且只有一个 Application 实例存在。和 WinForm 不同的是WPF Application默认由两部分组成 : App.xaml 和 App.xaml.cs,这有点类似于 Asp.Net WebForm,将定义和行为代码相分离。
微软把WPF中经常使用的功能都封装在 Application 类中了。 Application 类具体有以下功能:
- 跟踪应用程序的生存期并与之交互。
- 检索和处理命令行参数。
- 检测和响应未经处理的异常。
- 共享应用程序范围的属性和资源。
- 管理独立应用程序中的窗口。
- 跟踪和管理导航。
二.WPF应用程序的启动
关于如何在Visual Studio中创建一个“WPF应用程序”,前面的文章中已经说过了。请参见WPF入门教程系列一——基础。
1、在Visual Studio 2013中创建一个“WPF应用程序”,使用App.xaml文件定义启动应用程序。XAML从严格意义上说并不是一个纯粹的 XML 格式文件,它更像是一种 DSL(Domain Specific Language,领域特定语言),它的所有定义都会由编译器最后编译成代码。App.xaml文件默认内容如下图:
2、当然,如果你习惯了把启动写在代码中。你也可以跟WinForm中一样,在类中定义一个Main方法来实现对WPF应用程序的启动。
第一步:如下图,在“解决方案资源管理器”中使用鼠标左键选中App.xaml文件,然后鼠标右键,弹出“弹出菜单—》从项目中排除”,这样就在项目中去掉了我们刚才建立的App.xaml文件。
第二步:现在中添加一个新类,类名为App.cs。如下图。在“解决方案资源管理器”中使用鼠标左键选中“WpfApp1”项目,然后点击鼠标右键,弹出“弹出菜单”,按下图中所示操作。
第三步:在弹出的“添加新项”界面中,选中“类”,把名称修改为“App.cs”。如下图。
第四步:在“解决方案资源管理器”中双击App.cs(如下图),打开文件,然后可以分别写入以下三种方式的代码,进行启动效果的调试。
第一种启动应用程序的代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; namespace WpfApp1 { class App { [STAThread] static void Main() { // 定义Application对象作为整个应用程序入口 Application app = new Application(); // 方法一:调用Run方法 ,这种方式跟winform的调用一样,注意WindowGrid是要启动的窗口 WindowGrid win = new WindowGrid(); app.Run(win); } } }
备忘:[STAThread]的含义
[STAThread]
STAThread:Single Thread Apartment Thread.(单一线程单元线程)
[]是用来表示Attributes;[STAThread]
是一种线程模型,用在程序的入口方法上(在C#和VB.NET里是Main()方法),来指定当前线程的ApartmentState 是STA。用在其他方法上不产生影响。在aspx页面上可以使用AspCompat = "true" 来达到同样的效果。这个属性只在 Com Interop 有用,如果全部是 managed code 则无用。简单的说法:[STAThread]指示应用程序的默认线程模型是单线程单元 (STA)。启动线程模型可设置为单线程单元或多线程单元。如果未对其进行设置,则该线程不被初始化。也就是说如果你用的.NET Framework,并且没有使用COM Interop,一般不需要这个Attribute。其它的还有MTA(多线程套间)、Free Thread(自由线程)。[STAThread] attribute指示应用程序的 COM 线程模型是单线程单元。
而于此对应的多线程单元则是 [MTAThread] (多线程单元线程)COM 线程模型只适用于使用 COM interop 的应用程序。如果将此属性应用到不使用 COM interop 的应用程序,将没有任何效果。
COM 线程模型可设置为单线程单元或多线程单元。如果应用程序线程实际调用了 COM 组件,则仅为 COM interop 初始化该线程。如果没有使用 COM interop,则不初始化该线程。
第二种启动应用程序的代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; namespace WpfApp1 { class App { [STAThread] static void Main() { // 定义Application对象作为整个应用程序入口 Application app = new Application(); // 指定Application对象的MainWindow属性为启动窗体,然后调用无参数的Run方法 WindowGrid win = new WindowGrid(); app.MainWindow = win; // 是必须的,否则无法显示窗体 win.Show(); app.Run(); } } }
第三种启动应用程序的代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; namespace WpfApp1 { class App { [STAThread] static void Main() { // 定义Application对象作为整个应用程序入口 Application app = new Application(); // 通过Url的方式启动 app.StartupUri = new Uri("WindowGrid.xaml", UriKind.Relative); app.Run(); } } }
3. 上面的方法,最后执行的效果,如下图。
三、WPF应用程序的关闭
WPF应用程序的关闭只有在应用程序的 Shutdown 方法被调用时,应用程序才停止运行。 ShutDown 是隐式或显式发生,可以通过指定 ShutdownMode 的属性值来进行设置。
ShutdownMode选项 |
|
OnLastWindowClose(默认值): |
应用程序关闭时,或最后一个窗口关闭时关闭,或调用Application对象的Shutdown() 方法时,应用程序关闭。 |
OnMainWindowClose |
启动窗体关闭或调用Application对象的Shutdown()方法时,应用程序关闭。(和C#的Windows应用程序的关闭模式比较类似) |
OnExplicitShutdown |
只有在调用Application对象的Shutdown()方法时,应用程序才会关闭。 |
1. 对ShutdownMode选项的更改,可以直接在App.xaml中更改,如下代码。
<Application x:Class="WpfApp1.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="MainWindow.xaml" ShutdownMode="OnExplicitShutdown" > <Application.Resources> </Application.Resources> </Application>
2. 在代码文件(App.xaml.cs)中修改ShutdownMode选项,但必须注意这个设置要写在app.Run()方法之前 ,如下代码。
app.ShutdownMode = ShutdownMode.OnExplicitShutdown; app.Run(win);
Application对象的其他属性:
名称 |
说明 |
Current |
获取当前 AppDomain的 Application 对象。 |
Dispatcher |
获取与此 DispatcherObject 关联的 Dispatcher。 (继承自 DispatcherObject。) |
MainWindow |
获取或设置应用程序的主窗口。 |
Properties |
获取应用程序范围的属性集合。 |
ResourceAssembly |
获取或设置对于 WPF 应用程序的资源提供已装箱统一资源标识符 (URI) 的 Assembly 。 |
Resources |
获取或设置应用程序范围资源的集合,例如样式和画笔。 |
ShutdownMode |
获取或设置会导致 Shutdown 方法调用的情况。 |
StartupUri |
获取或设置自动显示的 UI ,当应用程序启动时。 |
Windows |
获取在应用程序中实例化窗口。 |
四、添加Application对象事件
名称 |
说明 |
Activated | 当应用程序成为前台应用程序时触发。 |
Deactivated | 当应用程序不再是前台应用程序时触发。 |
DispatcherUnhandledException | 如果异常是由应用程序引发,但未处理,触发。 |
Exit | 在应用程序关闭之前,触发,而且不能撤消。 |
FragmentNavigation | 发生在应用程序的一个浏览器启动导航到内容片段导航时,会立即发生,如果所需片段在当前目录,或者,在源 XAML 目录加载后,如果所需片段在其他内容。 |
LoadCompleted | 在导航到在应用程序中的一个浏览器的目录加载的分析完成并已呈现时触发。 |
Navigated | 当导航到在应用程序中使用的浏览器已找到的内容时触发,这时它可能还没有完成加载。 |
Navigating | 在一个新的导航由应用程序,一个浏览器请求发生。 |
NavigationFailed | 出现问题,则错误,当应用程序的一个浏览器导航到所请求的内容时。 |
NavigationProgress | 定期发生在应用程序中使用浏览器管理提供导航进度信息的下载过程。 |
NavigationStopped | 发生在一个浏览器的 StopLoading 方法在应用程序的调用,或者,如果新的导航由浏览器请求,在当前导航正在进行的。 |
SessionEnding | 当用户在注销或关闭操作系统关闭 Windows 会话时发生。 |
Startup | 当 Application 对象的 Run 方法调用,发生。 |
在应用程序中添加事件的方式有如下三种。
第一种方式
1、在App.xaml中做事件的绑定,在App.xaml.cs文件中添加事件的处理方法
2、添加完事件之后的app.xml文件代码如下
<Application x:Class="WpfApp1.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="MainWindow.xaml" ShutdownMode="OnExplicitShutdown" Activated="Application_Activated" Exit="Application_Exit"> <Application.Resources> </Application.Resources> </Application>
3、在App.xaml.cs文件的代码如下:
using System; using System.Collections.Generic; using System.Configuration; using System.Data; using System.Linq; using System.Threading.Tasks; using System.Windows; namespace WpfApp1 { /// <summary> /// App.xaml 的交互逻辑 /// </summary> public partial class App : Application { private void Application_Activated(object sender, EventArgs e) { } private void Application_Exit(object sender, ExitEventArgs e) { } } }
4.在使用以上方式添加事件之后,如果在Visual Studio中按F5 执行应用程序时,报以下错误“不包含适合于入口点的静态‘Main’方法”。这个错误是由于Visual Studio把项目文件(*.csproj)中原来自动生成的app.xaml相关的定义进行了修改。具体区别如下:
1) 直接新建的WPF项目中的有关App.xaml的定义如下:
<ApplicationDefinition Include="App.xaml"> <Generator>MSBuild:Compile</Generator> <SubType>Designer</SubType> </ApplicationDefinition>
2) Visual Studio把修改后的App.xaml的配置代码如下:
<Page Include="App.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page>
第一段代码中App.xaml在项目文件里面用ApplicationDefinition标签定义。第二段代码中App.xaml在项目文件里面用Page标签定义,这种定义是指App.xaml只是一个页面而已。
因此,只需要把项目文件中将App.xaml的配置由Page修改成ApplicationDefinition即可。
第二种方式
1、可以像是在WinForm中的Program类中写Main方法一样,在WPF中一样可以自定义一个app类中写main及其他相关事件。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; namespace WpfApp1 { class App { [STAThread] static void Main() { // 定义Application对象作为整个应用程序入口 Application app = new Application(); MainWindow win = new MainWindow(); app.ShutdownMode = ShutdownMode.OnMainWindowClose; app.MainWindow = win; //是必须的,否则无法显示窗体 win.Show(); app.Run(); app.Activated += app_Activated; app.Exit += app_Exit; } static void app_Activated(object sender, EventArgs e) { throw new NotImplementedException(); } static void app_Exit(object sender, ExitEventArgs e) { throw new NotImplementedException(); } } }
第三种方式
1.在App.xaml界面中,如下图位置1处,输入Exit事件名称,Visual Studio 2013会弹出一个菜单“新建事件处理程序”,双击这个菜单,Visual Studio 2013就会自动创建一个“Application_Exit”事件,如下图位置2处。
五、WPF应用程序生存周期
WPF应用程序的生命周期与执行顺序,用MSDN上的一张图片进行说明。下图显示了窗口的生存期中的主体事件的顺序。
(本文转载自:http://www.cnblogs.com/chillsrc/p/4471584.html)