Events play an important role in handling user interaction in WPF. Event is a message sent by the control that the program responds to by executing some application code. Each WPF control supports several events that can be handled.
Consider example below.
XAML
<Button Width="100" Height="30" FontSize="14" Content="Click Me" Click="Button_Click"></Button>
Code Behind
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("You clicked me");
}
In above example, Click is the event that is supported by Button control. Button_Click is the event handler (function) in code behind where I have written code to be executed when button is clicked. When we click on the button, message box will be shown with text “You clicked me”.
Type of Events
Below picture will give a quick overview of type of events in WPF.
1. Direct Events: Direct events have been in existence since windows forms. Direct events are only raised by the control where the event originates.
2. Routed Events: Routed events can be raised by multiple controls in visual tree and can be handled by multiple handlers.
To understand routed event, lets first understand control hierarchy in WPF.
XAML
<Window x:Class="WPFEvents.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ToolBar VerticalAlignment="Top">
<Button Width="100" Height="30" FontSize="14" Content="Click Me" Click="Button_Click"
Background="LightBlue"></Button>
</ToolBar>
</Grid>
</Window>
In above example, controls are arranged in hierarchal manner. Control hierarchy would be Window, Grid, ToolBar and Button. So button click event will be raised by Button, ToolBar, Grid and Window. Note: In above code we have specified click event handler for Button control only. We can also specify click event handler for ToolBar, Grid and Window which is explained in Attached Events section later in this post.
Routed events are of 2 types.
Bubbling Events: Bubbling events follow bottom - up approach and bubble up in the tree. Bubble events are first raised by the original/source control and then raised by the successive parent controls in the tree until the top level element (i.e window element ) is reached. In above case, Button control is the OriginalSource of the event. Hence Click event is first raised by Button control, then it is raised by ToolBar, Grid and Window.
Tunneling Events: Tunneling events follow top - down approach. Tunneling events are first raised by topmost control in the visual tree of original control, then raised by successive child controls until the OriginalSource control is reached. WPF Events with “Preview” keyword prefix to the event name are Tunneling events. Ex: Bubbling event “Click” has “PreviewClick” as tunneling event.
If we look at the function definition of Click event handler, RoutedEventArgs is passed as second argument. This object contains following event arguments.
Handled – Boolean value that Indicates that event is handled or not. Setting e.Handled = True means event is handled and will not be raised by successive controls.
Source - Control that raised the event.
OriginalSource - Source control that raised the event. Normally same as Source except some complex controls.
RoutedEvent - additional event related details.
3. Attached Events
So we have understood the concept of RoutedEvents. But in above example, how to specify event handler for parent controls like ToolBar, Grid and Window that does not provide Click event. This can be done Attached Events.
Attached events are the events that control can not define and raise by themselves, but still can provide handler for the events.
XAML
<Window x:Class="WPFEvents.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" ButtonBase.Click="Window_Click">
<Grid ButtonBase.Click="Grid_Click">
<ToolBar VerticalAlignment="Top" ButtonBase.Click="ToolBar_Click">
<Button Width="100" Height="30" FontSize="14" Content="Click Me" Click="Button_Click"
Background="LightBlue"></Button>
</ToolBar>
</Grid>
</Window>
Code Behind
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("You clicked me");
}
private void ToolBar_Click(object sender, RoutedEventArgs e)
{
}
private void Grid_Click(object sender, RoutedEventArgs e)
{
}
private void Window_Click(object sender, RoutedEventArgs e)
{
}
In above code, ButtonBase.Click is the attached event.
4. Application Level Events
Application level events are related to application lifetime and provided by Application object. They are handled in App.xaml and App.xaml.cs. Below are the events that are provided by Application Class.
Activated - Occurs when window is displayed for first time and each time when we switch back from other application to our application window.
Deactivated - Occurs when we switch to other application.
Startup - Occurs when the application is started.
Exit - Occurs when application is closed or shut down.
SessionEnding - Occurs when window session is ending like computer shut down.
DispatcherUnhandledException - When unhandled exception occurs in the application.
Example - App.xaml
<Application x:Class="WPFEvents.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml" Activated="Application_Activated">
<Application.Resources>
</Application.Resources>
</Application>
Code Behind - App.xaml.cs
public partial class App : Application
{
private void Application_Activated(object sender, EventArgs e)
{
}
}