如何使用代码添加事件处理程序 (WPF .NET)

可以使用标记或代码隐藏将事件处理程序分配给 Windows Presentation Foundation (WPF) 中的元素。 尽管通常在 Extensible Application Markup Language (XAML) 中分配事件处理程序,但有时可能需要在代码隐藏中分配事件处理程序。 例如,在以下情况使用代码:

  • 在加载包含元素的标记页之后,为元素分配事件处理程序。
  • 在加载将包含元素的标记页之后,添加一个元素并为其分配事件处理程序。
  • 完全在代码中定义应用程序的元素树。

重要

面向 .NET 7 和 .NET 6 的桌面指南文档正在撰写中。

先决条件

本文假定你对路由事件有基本的了解,并且已阅读路由事件概述。 若要遵循本文中的示例,如果熟悉 Extensible Application Markup Language (XAML) 并知道如何编写 Windows Presentation Foundation (WPF) 应用程序,将会很有帮助。

事件处理程序分配的语法

C# 支持使用以下方法分配事件处理程序:

  • += 运算符,公共语言运行时 (CLR) 事件处理模型中也使用此运算符。
  • UIElement.AddHandler 方法。

VB 支持使用以下方法分配事件处理程序:

示例

以下示例使用 XAML 定义名为 ButtonCreatedByXamlButton 并分配 ButtonCreatedByXaml_Click 方法作为其 Click 事件处理程序。 Click 是派生自 ButtonBase 的按钮的内置路由事件。

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

此示例使用代码隐藏来实现 ButtonCreatedByXaml_ClickButtonCreatedByCode_Click 处理程序,并将 ButtonCreatedByCode_Click 处理程序分配给 ButtonCreatedByCodeStackPanel1 元素。 事件处理程序方法只能在代码隐藏中实现。

// 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

单击 ButtonCreatedByXaml 并且其事件处理程序 ButtonCreatedByXaml_Click 以编程方式运行时:

  1. 向已构造的 XAML 元素树添加名为 ButtonCreatedByCode 的新按钮。
  2. 指定新按钮的属性,例如名称、内容和背景色。
  3. ButtonCreatedByCode_Click 事件处理程序分配给 ButtonCreatedByCode
  4. 将相同的 ButtonCreatedByCode_Click 事件处理程序分配给 StackPanel1

单击 ButtonCreatedByCode 时:

  1. Click 路由事件在 ButtonCreatedByCode 上引发。
  2. 触发分配给 ButtonCreatedByCodeButtonCreatedByCode_Click 事件处理程序。
  3. Click 路由事件在元素树中向上遍历到 StackPanel1
  4. 触发分配给 StackPanel1ButtonCreatedByCode_Click 事件处理程序。
  5. Click 路由事件继续向上遍历元素树,可能会触发分配给其他已遍历元素的其他 Click 事件处理程序。

ButtonCreatedByCode_Click 事件处理程序获取有关触发它的事件的以下信息:

  • sender 对象,它是分配了事件处理程序的元素。 处理程序首次运行时,senderButtonCreatedByCode,第二次运行时则为 StackPanel1
  • RoutedEventArgs.Source 对象,它是最初引发事件的元素。 在本示例中,Source 始终为 ButtonCreatedByCode

注意

路由事件和 CLR 事件之间的一个主要区别是,路由事件遍历元素树来查找处理程序,而 CLR 事件不遍历元素树,处理程序只能附加到引发事件的源对象。 因此,路由事件 sender 可以是元素树中的任何已遍历的元素。

有关如何创建和处理路由事件的详细信息,请参阅如何创建自定义路由事件处理路由事件

另请参阅