How to add an event handler using code (WPF .NET)

You can assign an event handler to an element in Windows Presentation Foundation (WPF) using markup or code-behind. Although it's customary to assign an event handler in Extensible Application Markup Language (XAML), sometimes you might have to assign an event handler in code-behind. For instance, use code when:

  • You assign an event handler to an element after the markup page that contains the element loads.
  • You add an element and assign its event handler after the markup page that will contain the element loads.
  • You define the element tree for your application entirely in code.

Important

The Desktop Guide documentation for .NET 7 and .NET 6 is under construction.

Prerequisites

The article assumes a basic knowledge of routed events, and that you've read Routed events overview. To follow the examples in this article, it helps if you're familiar with Extensible Application Markup Language (XAML) and know how to write Windows Presentation Foundation (WPF) applications.

Syntax for event handler assignment

C# supports event handler assignment using:

  • The += operator, which is also used in the common language runtime (CLR) event handling model.
  • The UIElement.AddHandler method.

VB supports event handler assignment using:

Example

The following example uses XAML to define a Button named ButtonCreatedByXaml and to assign the ButtonCreatedByXaml_Click method as its Click event handler. Click is a built-in routed event for buttons that derive from ButtonBase.

<StackPanel Name="StackPanel1">
    <Button
        Name="ButtonCreatedByXaml" 
        Click="ButtonCreatedByXaml_Click"
        Content="Create a new button with an event handler"
        Background="LightGray">
    </Button>
</StackPanel>

The example uses code-behind to implement the ButtonCreatedByXaml_Click and ButtonCreatedByCode_Click handlers, and to assign the ButtonCreatedByCode_Click handler to the ButtonCreatedByCode and StackPanel1 elements. Event handler methods can only be implemented in code-behind.

// The click event handler for the existing button 'ButtonCreatedByXaml'.
private void ButtonCreatedByXaml_Click(object sender, RoutedEventArgs e)
{
    // Create a new button.
    Button ButtonCreatedByCode = new();

    // Specify button properties.
    ButtonCreatedByCode.Name = "ButtonCreatedByCode";
    ButtonCreatedByCode.Content = "New button and event handler created in code";
    ButtonCreatedByCode.Background = Brushes.Yellow;

    // Add the new button to the StackPanel.
    StackPanel1.Children.Add(ButtonCreatedByCode);

    // Assign an event handler to the new button using the '+=' operator.
    ButtonCreatedByCode.Click += new RoutedEventHandler(ButtonCreatedByCode_Click);

    // Assign an event handler to the new button using the AddHandler method.
    // AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonCreatedByCode_Click);

    // Assign an event handler to the StackPanel using the AddHandler method.
    StackPanel1.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonCreatedByCode_Click));
}

// The Click event handler for the new button 'ButtonCreatedByCode'.
private void ButtonCreatedByCode_Click(object sender, RoutedEventArgs e)
{
    string sourceName = ((FrameworkElement)e.Source).Name;
    string senderName = ((FrameworkElement)sender).Name;

    Debug.WriteLine($"Routed event handler attached to {senderName}, " +
        $"triggered by the Click routed event raised by {sourceName}.");
}
' The click event handler for the existing button 'ButtonCreatedByXaml'.
Private Sub ButtonCreatedByXaml_Click(sender As Object, e As RoutedEventArgs)

    ' Create a new button and specify button properties.
    Dim ButtonCreatedByCode As New Button With {
        .Name = "ButtonCreatedByCode",
        .Content = "New button and event handler created in code",
        .Background = Brushes.Yellow
    }

    ' Add the new button to the StackPanel.
    StackPanel1.Children.Add(ButtonCreatedByCode)

    ' Assign an event handler to the new button using the AddHandler statement.
    AddHandler ButtonCreatedByCode.Click, AddressOf ButtonCreatedByCode_Click

    ' Assign an event handler to the new button using the AddHandler method.
    ' ButtonCreatedByCode.AddHandler(ButtonBase.ClickEvent, New RoutedEventHandler(AddressOf ButtonCreatedByCode_Click))

    ' Assign an event handler to the StackPanel using the AddHandler method.
    StackPanel1.AddHandler(ButtonBase.ClickEvent, New RoutedEventHandler(AddressOf ButtonCreatedByCode_Click))

End Sub

' The Click event handler for the new button 'ButtonCreatedByCode'.
Private Sub ButtonCreatedByCode_Click(sender As Object, e As RoutedEventArgs)

    Dim sourceName As String = CType(e.Source, FrameworkElement).Name
    Dim senderName As String = CType(sender, FrameworkElement).Name

    Debug.WriteLine($"Routed event handler attached to {senderName}, " +
        $"triggered by the Click routed event raised by {sourceName}.")

End Sub

When ButtonCreatedByXaml is clicked and its event handler runs, ButtonCreatedByXaml_Click programmatically:

  1. Adds a new button named ButtonCreatedByCode to the already constructed XAML element tree.
  2. Specifies properties for the new button, such as the name, content, and background color.
  3. Assigns the ButtonCreatedByCode_Click event handler to ButtonCreatedByCode.
  4. Assigns the same ButtonCreatedByCode_Click event handler to StackPanel1.

When ButtonCreatedByCode is clicked:

  1. The Click routed event is raised on ButtonCreatedByCode.
  2. The ButtonCreatedByCode_Click event handler assigned to ButtonCreatedByCode is triggered.
  3. The Click routed event traverses up the element tree to StackPanel1.
  4. The ButtonCreatedByCode_Click event handler assigned to StackPanel1 is triggered.
  5. The Click routed event continues up the element tree potentially triggering other Click event handlers assigned to other traversed elements.

The ButtonCreatedByCode_Click event handler obtains the following information about the event that triggered it:

  • The sender object, which is the element that the event handler is assigned to. The sender will be ButtonCreatedByCode the first time the handler runs, and StackPanel1 the second time.
  • The RoutedEventArgs.Source object, which is the element that originally raised the event. In this example, the Source is always ButtonCreatedByCode.

Note

A key difference between a routed event and a CLR event is that a routed event traverses the element tree, looking for handlers, whereas a CLR event doesn't traverse the element tree and handlers can only attach to the source object that raised the event. As a result, a routed event sender can be any traversed element in the element tree.

For more information on how to create and handle routed events, see How to create a custom routed event and Handle a routed event.

See also