Application对象

  当一个WPF应用程序启动时,首先会实例化一个全局唯一的Application对象,类似于WinForm下的Application类,用于控制整个应用程序,该类将用于追踪应用程序打开的窗口。在应用程序打开或关闭的时候能够触发相应的事件。

创建Application对象

手动创建Application应用程序对象过程:

1、  使用VS创建WPF应用程序,命名为WPFDemo。然后手动清除App.xaml文件。

2、  添加Startup.cs类,并添加程序代码。如下:

using System.Windows;//添加windows命名空间

namespace WPFDemo
{
public class Startup
{
[STAThread]
public static void Main()
{
Application app = new Application();//创建application对象 MainWindow win = new MainWindow();//实例化窗口对象,作为应用程序主窗口 win.Title = "应用程序主窗口";//指定应用程序窗口标题 app.Run(win);//调用Run方法开始运行应用程序
}
}
}

3、  F5启动应用程序。

关闭应用程序

Application类提供了一个ShutdownMode的枚举属性值,可以供开发人员指定应用程序的关闭模式。开发人员可以在Application的OnStartup事件为这个属性赋值,也可以在XAML文件中设置这个属性。

ShutdownModel 枚举值

枚举值

说明

OnLastWindoClose

当最后一个窗口关闭或在调用Application.Shutdown方法时,应用程序将关闭。

OnMainWindowClose

主窗口关闭或者调用Application.Shutdow方法时,应用程序关闭。

OnExplicitShutdown

即使所有窗口都被关闭,应用程序也不会终止。这个方法适用于一些长时间运行后台任务的场合。当显式调用Application.Shutdown方法后,应用程序才会退出。

Application类OnStartup事件中设置ShutdownMode枚举值。

  protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
this.ShutdownMode = ShutdownMode.OnMainWindowClose;
}

App.xaml中指定的ShutdownMode值

<Application x:Class="WPFDemo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFDemo"
StartupUri="MainWindow.xaml"
ShutdownMode="OnLastWindowClose">
<Application.Resources> </Application.Resources>
</Application>

应用程序事件

应用程序执行将会按照顺序触发下列事件。

1、  Startup:应用程序启动事件。

2、  Activated:当应用程序的顶层窗口被激活时触发此事件。

3、  Deactiveated:当应用程序的顶层窗口失去焦点时触发此事件。

4、  DispatherUnhandledException:当应用程序的产生未处理异常时触发此事件。

5、  SessionEnding:当Windows会话被终止时触发此事件,例如用户注销或关闭计算机。

6、  Exit:当应用程序因为某种原因而被关闭时触发此事件。

Startup 应用程序启动事件

该事件在Run方法被调用后触发,这个事件通常用于放置应用程序范围的初始化信息。获取和设置应用程序范围的配置,处理命令行参数等。该事件提供了StartupEventArgs类型的参数,包含了命令行参数信息。

Startup事件可以完成下列任务。

(1)、处理命令行参数。

(2)、打开主窗口。

(3)、初始化应用程序范围的资源。

(4)、初始化应用程序范围的属性。

Startup事件,首先在App.xaml文件中,去掉StartupUri属性,关联Startup事件处理器。

<Application x:Class="WPFDemo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFDemo"
Startup="Application_Startup">
<Application.Resources> </Application.Resources>
</Application>

接下来在 App.xaml.cs 文件中添加下列事件处理器

private void Application_Startup(object sender, StartupEventArgs e)
{
  MainWindow win = new WPFDemo.MainWindow();
  win.Show();
}

在实际项目开发中,OnStartup中的代码可以非常复杂,可以读取应用程序资源或读取应用程序设置中读取配置信息,配置参数等。

Activated和Deactiveated事件

应用程序的激活与Window的激活和取消激活类似,但应用程序的激活通常是指全局应用程序的激活,通常发生在如下情况下:

1、  应用程序打开第一个窗口。

2、  用户使用Alt+Tab组合件或者使用任务管理器切换到该应用程序。

3、  用户单击应用程序中一个窗口的任务栏按钮。

与窗口不同的是,一旦应用程序激活,在应用程序停用前都不会再次引发Activated事件。

在上面示例中新增一个名为Window2.xaml的窗口。并修改OnStartup事件处理器的代码,使其启动时能够显示两个窗口。

    private void Application_Startup(object sender, StartupEventArgs e)
    {
    MainWindow win = new WPFDemo.MainWindow();
    win.Title = "通过OnStartup事件启动的主窗口";
    win.Show();     Window2 win2 = new Window2();
    win2.Title = "通过OnStartup时间启动的第二个窗口";
    win.Show();
    }
      //重载OnActivated事件,在窗体被激活时触发。
protected override void OnActivated(EventArgs e)
{
System.Diagnostics.Debug.Write("当前应用程序被激活");
foreach (Window win in Windows)
{
if (win.IsActive)
{
System.Diagnostics.Debug.WriteLine("当前的活动窗口是:" + win.Title);
}
}
base.OnActivated(e);
}
       //重载OnDeactivated事件,在窗体被取消激活时触发。
protected override void OnDeactivated(EventArgs e)
{
base.OnDeactivated(e);
System.Diagnostics.Debug.WriteLine("当前应用程序停止激活");
}

DispatherUnhandledException事件

DispatcherUnhandledException 给开发人员一个处理应用程序为处理的异常的地方。在window1.xaml.cs 的构造函数中抛出一个异常。

public Window1()
{
  InitializeComponent();
  throw new Exception("演示DispatherUnhandledException的作用,这里抛出一个异常");
}

然后在App.xaml中添加对DispatherUnhandledException属性的赋值,最后在App.xaml.cs中添加一些代码来显示一个自定义的错误窗口。

      private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
string err = "异常信息:" + e.Exception.Message.ToString();
MessageBox.Show(err);
e.Handled = true;
}

运行应用程序将会弹出下面对话框

SessionEnding事件 – 注销或关闭系统 

当Windows操作系统的会话终止时,则会触发SessionEnding事件。SessionEnding事件有一个SessionEndingCancelEventArgs类型的参数,该参数有一下Cancel布尔属性,当设置为true时,将会取消windows的会话终止行为。除此之外,还可以使用ReasonSessionEnding枚举类型的属性,来检测终止会话的类型,该属性有下面两个值:

1、  Logoff :会话正在结束的原因是用户正在注销。

2、  Shutdown : 会话正在结束的原因是用户正在关闭Windows。

下面演示如何使用SessionEnding事件,当windows应用程序终止时,弹出一个对话框窗口提示用户进行选择。

App.xaml 文件制定SessionEnding事件

<Application x:Class="WPFDemo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFDemo"
Startup="Application_Startup"
SessionEnding="Application_SessionEnding"
>
<Application.Resources> </Application.Resources>
</Application>

在App.xaml.cs文件中添加如下代码

     private void Application_SessionEnding(object sender, SessionEndingCancelEventArgs e)
{
//询问用户是否允许终止会话
string msg = string.Format("{0} 是否要终止Windows会话?", e.ReasonSessionEnding);
MessageBoxResult result = MessageBox.Show(msg, "Session Ending", MessageBoxButton.YesNo);
if (result == MessageBoxResult.No)
{//如果点击yes,允许终止,否则禁止终止会话
e.Cancel = true;
}
}

运行应用程序,当windows终止会话时,应用程序会弹出如下图的对话框,如果用户点击“取消”按钮,则会取消终止Windows会话。

Exit事件

当应用程序退出时,将触发Exit事件。下面演示应用程序退出时,向用户隔离区写入应用程序日志和应用程序状态。首先在App.xaml代码中添加事件处理器声明

App.xaml文件

<Application x:Class="WPFDemo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFDemo"
Startup="Application_Startup" DispatcherUnhandledException="Application_DispatcherUnhandledException" SessionEnding="Application_SessionEnding"
Exit="Application_Exit"
> <Application.Resources> </Application.Resources>
</Application>

在App.xaml.cs文件中添加如下代码

        /// <summary>
/// 应用程序退出标志
/// </summary>
public enum ApplicationExitCode
{
Success = 0,
Failure = 1,
CantWriteToApplicationLog = 2,
CantPersistApplicationState = 3
} /// <summary>
/// 应用程序退出
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Application_Exit(object sender, ExitEventArgs e)
{
try
{
if (e.ApplicationExitCode == (int)ApplicationExitCode.Success)
{
WriteApplicationLogEntry("Failure", e.ApplicationExitCode);
}
else
{
WriteApplicationLogEntry("Success", e.ApplicationExitCode);
}
}
catch
{
//写入应用程序失败时,更新退出代码已反映出写入失败
e.ApplicationExitCode = (int)ApplicationExitCode.CantWriteToApplicationLog; } //保存应用程序状态
try
{
PersistApplicationState();
}
catch
{
//写入应用程序失败时,更新退出代码已反映出写入失败
e.ApplicationExitCode = (int)ApplicationExitCode.CantPersistApplicationState;
}
}
/// <summary>
/// 记录应用程序日志
/// </summary>
/// <param name="message"></param>
/// <param name="exitCode"></param>
private void WriteApplicationLogEntry(string message, int exitCode)
{
//写入日志项到用户隔离存储区
IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForAssembly();
using (Stream stream = new IsolatedStorageFileStream("log.txt", FileMode.Append, FileAccess.Write, store))
{
using (StreamWriter writer = new StreamWriter(stream))
{
string entry = string.Format("{0}:{1} - {2}", message, exitCode, DateTime.Now);
writer.WriteLine(entry);
}
}
}
/// <summary>
/// 记录应用程序状态日志
/// </summary>
private void PersistApplicationState()
{
//保存应用程序状态到用户隔离存储区
IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForAssembly();
using (Stream stream = new IsolatedStorageFileStream("state.txt", FileMode.Create, store))
using (StreamWriter writer = new StreamWriter(stream))
{
//可以在这里更改为自定义的保存应用程序状态的程序代码
foreach (DictionaryEntry entry in this.Properties)
{
writer.WriteLine(entry.Value);
}
}
}

上面代码中,首先定义一个推出的枚举类型。在应用程序Exit事件触发,根据不同的推出写入不同的信息到用户的隔离存储区。通常在Exit事件中保存应用程序的配置信息,当应用程序启动时可以在Startup加载配置信息。

Application类的任务 

处理命令行参数

在WPF应用程序中,可以使用两种方法来处理命令行参数。一种是通过Environment对象的静态GetCommandLineArgs方法,另一种是通过相应Application类的Startup事件。该事件提供了SartupEventArgs类型的参数,该参数中包含了从命令行提示符或桌面传递的命令行参数。

使用Startup中 StartupEventArgs获取命令行参数

 在App.xaml中指定Startup=”Application_Startup”事件,并在App.xaml.cs Startup事件中添加下列代码

        private void Application_Startup(object sender, StartupEventArgs e)
{
//该bool值将从命令行参数中获取。如果制定了特定的命令行参数,则将该bool值设置为true;
bool startMinimized = false;
//命令行参数是一个字符串数组类型,遍历参数数组,寻找特定的命令行参数。 for (int i = 0; i < e.Args.Length; i++)
{
if (e.Args[i] == "/StartMinimized")
{
startMinimized = true;
}
} //创建应用程序主窗口,如果指定了命令行参数,则最小化运行应用程序。并在窗口显示第一个命令行参数。 Window1 win = new Window1(); if (startMinimized)
{
win.WindowState = WindowState.Minimized;
win.Content = "当前命令行参数" + e.Args[0];
}
win.Show();
}

下面在项目中设置命令行参数来调试应用程序。首先在项目名称点击【右键】选择【属性】【调试】然后再命令行参数设置/StartMinimized。(如下图)然后启动应用程序发现应用程序以最小化方式运行,并且在窗体中显示“当前命令行参数/StartMinimized”

也可以使用CMD命令加参数的方式启动应用程序(如下图):

1、  打开CMD命令窗口。

2、  使用cd命令进入应用程序所在的文件夹。 命令: cd 目录名称

3、  然后执行exe应用程序,并指定参数。命令:WPFDemo.exe /StartMinimized

使用Environment的GetCommandLineArgs方法获取命令行参数

 只需要将上面代码中获取参数部分替换为

string[] args = Environment.GetCommandLineArgs();

完整代码如下:

        private void Application_Startup(object sender, StartupEventArgs e)
{
//该bool值将从命令行参数中获取。如果制定了特定的命令行参数,则将该bool值设置为true; bool startMinimized = false; ///使用Environment的GetCommandLineArgs方法获取命令行参数
string[] args = Environment.GetCommandLineArgs(); //命令行参数是一个字符串数组类型,遍历参数数组,寻找特定的命令行参数。
foreach (string arge in args)
{
if (arge == "/StartMinimized")
{
startMinimized = true; }
}
//创建应用程序主窗口,如果指定了命令行参数,则最小化运行应用程序。并在窗口显示第一个命令行参数。 Window2 win = new Window2();
if (startMinimized)
{
win.WindowState = WindowState.Minimized;
win.Content = "当前命令行参数" + e.Args[0];
}
win.Show();
}

 

单实例应用程序

一个WPF应用程序可以被打开多次,并产生多个进程。在很多场景下只能允许运行一个应用程序。下面提供两种方式创建单实例的应用程序

1、  使用System.Threading命名空间中的Mutex,称为同步基元或者互斥元。

2、  使用windowsFormsApplicationBase类实现单实例应用程序。

使用System.Threading命名空间的Mutex创建单实例应用程序。

1、  引用System.Threading命名空间,定义Mutex对象。

2、  重载Startup方法

3、  运行两个WPF应用程序会弹出“已存在一个应用程序实例”对话框,并关闭当前应用程序。

       Mutex mutex;

        protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
string mutexName = "WPFDemo";
bool CreatedNew;
mutex = new Mutex(true, mutexName, out CreatedNew); if (!CreatedNew)//如果有存在的实例,则关闭当前实例
{
MessageBox.Show("已存在一个应用程序实例");
Shutdown();
}
}

使用windowsFormsApplicationBase实现单实例应用程序。 

1、  添加Microsoft.VisualBasic.dll程序集的引用。

2、  新建SingleApplicationBase类,并添加

  Microsoft.VisualBasic 和 Microsoft.VisualBasic.ApplicationServices命名空间。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text; //添加命名空间
using Microsoft.VisualBasic;
using Microsoft.VisualBasic.ApplicationServices; namespace SingleInstanceWithCommunication
{
public class SingleApplicationBase : WindowsFormsApplicationBase
{
public SingleApplicationBase()
{
this.IsSingleInstance = true; //设置为允许单例模式
} private App wpfApp; protected override bool OnStartup(StartupEventArgs eventArgs)
{
wpfApp = new App();
wpfApp.Run();
return false;
}
//当有其他应用程序实例化时,则出发此事件,将WPF应用程序中显示一个新的窗口
protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
{
base.OnStartupNextInstance(eventArgs);
Console.WriteLine("启动实例");
} }
}

3、  右键选择App.xaml页面的属性,更改生成操作位Page。

4、  然后再App.xaml.cs中添加代码。重载Onstartup事件,设置启动页面,然后创建应用程序启动的Main方法。

        protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow win = new SingleInstanceWithCommunication.MainWindow();
this.MainWindow = win;
win.Show();
} [STAThread]
public static void Main(string[] args)
{
SingleApplicationBase sab = new SingleApplicationBase();
sab.Run(args);
}

5、多次启动应用程序,发现同时只能运行一个实例。

WPF 10天修炼 第三天- Application全局应用程序类的更多相关文章

  1. Application全局应用程序类

    当一个WPF应用程序启动时,先会实例化一个全局的唯一的Application.如果开发人员熟悉Windows Form编程,会知道在SystemWindowsForm命名空间中有一个Applicati ...

  2. WPF 10天修炼 第八天 - 形状、画刷和变换

    图形 在WPF中使用绘图最简单的就是使用Shape类.Shape类继承自FrameworkElement,是一个专门用来绘图的类.Shape类中年派生的类有直线.矩形.多边形和圆形等. System. ...

  3. WPF 10天修炼 第一天- 入门

    简介 WPF技术基于DirectX,完美的整合了矢量图形.2D或3D绘图技术.文件及多媒体技术.WPF将开发人员和设计人员的职责清楚的分离,提供了一种声明编程语言XAML.同时Expression B ...

  4. WPF 10天修炼 第二天- XAML语言

    XAML是什么 XAML是一种与.NET CLR紧密集成的声明性UI标记语言.XAML中的对象元素对应到CLR中的类型或结构.XAML命名空间对应到CLR中类的命名空间,元素类型则对应到CLR中的类型 ...

  5. Thinkphp源码分析系列(三)– App应用程序类

    // +---------------------------------------------------------------------- // | ThinkPHP [ WE CAN DO ...

  6. WPF 10天修炼 第十天- WPF数据绑定

    WPF数据绑定 数据绑定到元素属性是将源对象指定为一个WPF元素,并且源属性是一个依赖属性,依赖属性内置了变更通知.当改变源对象依赖属性值之后,绑定目标可以立即得到更新,开发人员不需要手动编写响应事件 ...

  7. WPF 10天修炼 第七天- WPF资源、样式、控件模板

    WPF资源 对象资源 WPF允许在XAML标记的任意位置定义资源.比如在特定的控件.窗口或应用程序级别定义资源,WPF资源系统提供的对象资源有如下好处: 1.  高效:使用对象资源可以在一个地方定义而 ...

  8. WPF 10天修炼 第四天- WPF布局容器

    WPF布局 WPF的窗口也就是Window类,是一个内容控件,该控件派生自ContentControl.内容控件有一个Content属性,该属性有一个限制,只能放置一个用户界面元素,或一个字符串.为了 ...

  9. WPF 10天修炼 第九天 - 几何图形

    几何图形 使用LineGeometry.RectangleGeometry.EllipseGeometry对象分别绘制直线.矩形.椭圆. 使用GeometryGroup可以绘制组合图形. <Wi ...

随机推荐

  1. 分布式唯一ID生成方案是什么样的?(转)

    一.前言 分布式系统中我们会对一些数据量大的业务进行分拆,如:用户表,订单表.因为数据量巨大一张表无法承接,就会对其进行分库分表. 但一旦涉及到分库分表,就会引申出分布式系统中唯一主键ID的生成问题, ...

  2. Promise async-await 异步解决方案

    1.简介:     async和await在干什么,async用于申明一个function是异步的,而await可以认为是async wait的简写,等待一个异步方法执行完成. 2.基本语法   在C ...

  3. MySQL数据库8.0.15 安装教程

    第一步:安装MySQL服务 这里下载完成的是一个压缩文件,直接将里面的‘mysql-8.0.15-winx64'文件夹解压到你想要安装的路径即可,我是直接安装在C盘的. 解压完后的文件路径如下图: 在 ...

  4. 回温js算法

    ---恢复内容开始--- 一,冒泡排序. 具体算法描述如下: <1>.比较相邻的元素.如果第一个比第二个大,就交换它们两个: <2>.对每一对相邻元素作同样的工作,从开始第一对 ...

  5. U68364 _GC滑迷宫

    题目背景 _GC买了一双蔡徐坤一代. 题目描述 _GC进入了一个n*m的迷宫.本题的特殊之处在于,_GC只能滑着走.具体来说就是,选定一个方向后,_GC会一直向该方向滑,直到撞到墙.会给出_GC的起始 ...

  6. canvas基础(一)

    获取元素与画笔: <canvas id="myCanvas" width="200" height="200">该浏览器不支持c ...

  7. Python中布尔值是False的所有值

    在python中以下都是False:为0的,空集合,空字符串,空值None >>> bool(0) False >>> bool(-0) False >> ...

  8. [AH2017/HNOI2017]大佬

    题目描述 人们总是难免会碰到大佬.他们趾高气昂地谈论凡人不能理解的算法和数据结构,走到任何一个地方,大佬的气场就能让周围的人吓得瑟瑟发抖,不敢言语. 你作为一个 OIER,面对这样的事情非常不开心,于 ...

  9. BZOJ2127Happiness

    题目描述 高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文 ...

  10. JavaScript速记

    JavaScript常见知识点积累,包括数据类型.数值转换.对象.原型与原型链.作用域与闭包等等,持续整理更新,如有错误请指正,甚是感激 本文链接:JavaScript那些磨人的小妖精 作者:狐狸家的 ...