Introduction
This article is a tutorial for beginners. It talks about lifetime events of an WPF application.
One common problem for WPF newbies is the lack of understanding of order of events which confuses them when they try to add initialization, cleanup or safe shutdown code.
In this article I will underlie basic concepts regarding that.
Events in WPF
We can classify events in WPF as lifetime events, input
events and custom events.
Input events are events related to mouse, keyboard, stylus and Gestures.
Custom events are events that developers implement by declaring their own delegate and an event wrapper surrounding it.
We will be concentrating only on lifetime events.
Lifetime events
Any object undergoes creation, use and destruction in its lifetime. Here I describe the lifetime events of a WPF object specifically Window and Application. These objects derive from Framework element.
I will be describing lifetime events below in the order they occur.
First Init order and then shutdown order.
Init order of events:
Any WPF object that derives from Framework class will undergo initialized, loaded and unloaded. Although the sample program shows Application, Window and a child object (simple button) overriding and handling lifetime events.
Startup: (Application)
This is the first lifetime event of Application to get fired. This is fired when
Application.Run()
is called on the main window. But before the main window is shown. Please note that
Application.Run()
is abstracted from the user. If you want to check the compiler generated code, search under your
projec\obj folder for file named App.g.i.cs (g stands for generated).
This is the event where you can process any commandline arguments received by your application.
Initialized: (Window)
This is the first lifetime event of window to get fired. This is an ordinary .Net event and not a routed event. When this event is fired at window level it means all its nested child controls are also already initialized. So child controls will fire their Initialized event followed by parent control and finally by Window. (Check the sample program, you will find that "Button_Initialized" event is fired before "Window_Initialized")
This occurs once the window is instantiated. This event is at the level of base class
FrameworkElement
. Note that Styles and databinding will not be applied at this level. An interesting thing is
FrameworkElement
defines services for Animation, styles and DataBinding
.
SourceInitialized : (Window)
Acquire a proper legacy handle to your window. But still your window is not visible.
It is worthy to note that this top level Window event has no equivalent for child controls. Because none of the WPF child controls have a HWND associated with it, strikingly different from Winforms model. Check this link for further understanding http://www.codeproject.com/Articles/133632/Win32-Handle-HWND-WPF-Objects-A-Note
Activated: (Application)
Called every time when this app's window comes foreground and also the first time app's window is rendered. Please note that only after this event window's
Activated
event will be fired which actually makes sense
Activated: (Window)
Equivalent to GotFocus
of a control. Called every time when window comes foreground and also the first time window is rendered. Only after this event window loaded event
isfired
.
Loaded: (Window)
Your entire window is ready. Last stop before rendering. All animation, styles and databinding will be ready here. Any visual tweaks needs to be done here.
This works in reverse order when compared with Initialized event. It is raised from root to child element from the fully constructed logical element tree. So window Load event will be raised first followed by any child element events.
(Check the sample program, you will find that "Button_Loaded" event is fired after "Window_Loaded")
ContentRendered: (Window)
As the name implies it occurs after content was rendered. If there is no content this event will not be fired at all. Don't do any visual tweaks here. From here you may set a flag for your business logic that window is up, running and shown to the user for the first time.
Shutdown order of events:
Closing: (Window)
Trigger can be user action or programmatic. user action can be direct like clicking on close button. Logging of from windows did not rais this event. (SessionEnding
event is handled in sample but not discussed here) In case of your program it can be a call to
Window.Close()
or Application.ShutDown()
. In any case the event can be cancelled by overriding
OnClosing()
and setting CancelEventArgs.Cancel
to true.
Deactivated: (Window)
Happens if window loses focus (this is window equivalent to
control.GotFocus()
) or closed.
Deactivated: (Application)
Happens if user switches to another application (by Alt-Tab, taskbar or task manager etc.) or as effect of application closure.
Closed: (Window)
Window is closed but window elements are accessible. Last place to access them if there is a reason. Note after this window unloaded will be fired.
Exit: (Application)
Last but not least. Only the Run()
method returns. (please refer to startup event above for note on Run()
method). But if you have written your custom main()
method instead of a generated one still you can add some business logic code here. Any quick resource freeing can be done here.
Other lifetime events
Unloaded
On wpf web apps on page navigation they occur. And also when the window theme changes this will be fired. (Verify the same by changing your windows theme when sample program is running.)
SessionEnding
This event is fired when user logs off from the system. Same can be cancelled by setting SessionEndingCancelEventArgs e.cancel
as true.
About
the Sample code
Please find a WPF app that lists lifetime events of a window and application as they occur individually and combined. Because when some of application events are raised, window not yet created so it becomes important to somehow record the event data. Although simple logging is suffice I
modeled the same using a WPF hosted WCF client. Run "DataLogHostSvc" logger window before you run "OrderOfEvents" project. Other than that the attached sample is self-explanatory.
Note: As this sample uses net.tcp binding your windows firewall might block it and you need to add the exception.
References
http://msdn.microsoft.com/en-us/library/ms754221.aspx
Book: Pro WPF in C# 2010 - Matthew MacDonald