1. 程式人生 > >【WPF學習】第二十六章 Application類——應用程式的生命週期

【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系統)還是取消關閉。