WPF 10天修煉 第三天- Application全局應用程序類

Application對象windows

  當一個WPF應用程序啓動時,首先會實例化一個全局惟一的Application對象,相似於WinForm下的Application類,用於控制整個應用程序,該類將用於追蹤應用程序打開的窗口。在應用程序打開或關閉的時候可以觸發相應的事件。數組

 

建立Application對象app

手動建立Application應用程序對象過程:ide

一、  使用VS建立WPF應用程序,命名爲WPFDemo。而後手動清除App.xaml文件。函數

二、  添加Startup.cs類,並添加程序代碼。以下:this

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方法開始運行應用程序
        }
    }
}

三、  F5啓動應用程序。spa

 

關閉應用程序操作系統

         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>    

應用程序事件  

應用程序執行將會按照順序觸發下列事件。

一、  Startup:應用程序啓動事件。

二、  Activated:當應用程序的頂層窗口被激活時觸發此事件。

三、  Deactiveated:當應用程序的頂層窗口失去焦點時觸發此事件。

四、  DispatherUnhandledException:當應用程序的產生未處理異常時觸發此事件。

五、  SessionEnding:當Windows會話被終止時觸發此事件,例如用戶註銷或關閉計算機。

六、  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的激活和取消激活相似,但應用程序的激活一般是指全局應用程序的激活,一般發生在以下狀況下:

一、  應用程序打開第一個窗口。

二、  用戶使用Alt+Tab組合件或者使用任務管理器切換到該應用程序。

三、  用戶單擊應用程序中一個窗口的任務欄按鈕。

與窗口不一樣的是,一旦應用程序激活,在應用程序停用前都不會再次引起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枚舉類型的屬性,來檢測終止會話的類型,該屬性有下面兩個值:

一、  Logoff :會話正在結束的緣由是用戶正在註銷。

二、  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命令加參數的方式啓動應用程序(以下圖):

一、  打開CMD命令窗口。

二、  使用cd命令進入應用程序所在的文件夾。 命令: cd 目錄名稱

三、  而後執行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應用程序能夠被打開屢次,併產生多個進程。在不少場景下只能容許運行一個應用程序。下面提供兩種方式建立單實例的應用程序

一、  使用System.Threading命名空間中的Mutex,稱爲同步基元或者互斥元。

二、  使用windowsFormsApplicationBase類實現單實例應用程序。

使用System.Threading命名空間的Mutex建立單實例應用程序。

一、  引用System.Threading命名空間,定義Mutex對象。

二、  重載Startup方法

三、  運行兩個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實現單實例應用程序。 

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

二、  新建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("啓動實例");
        }

    }
}

三、  右鍵選擇App.xaml頁面的屬性,更改生成操做位Page。

四、  而後再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);
        }    

五、屢次啓動應用程序,發現同時只能運行一個實例。

相關文章
相關標籤/搜索