使用AddHandler 方法处理已经被处理的事件

所有的UIElement 实例及其子类的实例都有一个AddHandler 方法。通过该方法可以为指定的路由事件添加处理函数,并将该处理程序添加到当前元素的处理程序集合中。

AddHandler 方法有一个AddHandler(RoutedEvent, Delegate, Boolean) 的重载。

第一个参数表示指定的路由事件;

第二个参数指定事件的处理函数;

第三个参数表明是否在事件被标记为已处理的情况(e.Handled=true)下还继续处理该事件。

WPF中,事件是根据冒泡向上路由传递的,如果我们不想让事件继续传递,可以在路由的某个节点的处理函数中将e.Handled=true,表示事件已经被处理,那么后续的路由中该事件将不会被处理。但是如果使用AddHandler 方法并将第三个参数设置为true ,即使事件在之前被标记为已处理(e.Handled=true),通过AddHandler 方法添加的事件处理函数依然会执行。

 下面的例子说明AddHandler 方法第三个参数的具体作用。

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="test"
        KeyDown="winMain_KeyDown">
    <StackPanel Orientation="Vertical" Name="spMain">
        <Label Content="Some good movies:"/>
        <StackPanel Orientation="Horizontal" Margin="10" KeyDown="spLawrence_KeyDown">
            <Label Content="Lawrence of Arabia" FontWeight="Bold"/>
            <Label Content="David Lean"/>
            <Button Content="Like" Padding="8,0"/>
            <TextBox Width="75" Margin="5,2" KeyDown="tbLawrence_KeyDown"/>
        </StackPanel>
    </StackPanel>
</Window>
上面的XAML代码中 Window下面有两个 StackPanel ,并且在最底层的 StackPanel 中有一个 TextBox 控件,我给 TextBox 和包含它的底层 StackPanel 以及 Window注册 KeyDown 事件,而作为 Window根元素的 StackPanel 在代码中使用 AddHandler 方法注册 KeyDown 事件。

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            spMain.AddHandler(UIElement.KeyDownEvent, (KeyEventHandler)spMain_KeyDown, true);
        }

        private void tbLawrence_KeyDown(object sender, KeyEventArgs e)
        {
            DumpInfo("tbLawrence_KeyDown", sender, e.Source);
        }

        private void spLawrence_KeyDown(object sender, KeyEventArgs e)
        {
            DumpInfo("spLawrence_KeyDown", sender, e.Source);
            e.Handled = true;    // The event stops here
        }

        private void spMain_KeyDown(object sender, KeyEventArgs e)
        {
            DumpInfo("spMain_KeyDown", sender, e.Source);
        }

        private void winMain_KeyDown(object sender, KeyEventArgs e)
        {
            DumpInfo("winMain_KeyDown", sender, e.Source);
        }

        private void DumpInfo(string title, object sender, object source)
        {
            System.Console.WriteLine(title + "   sender=" + sender.ToString() + "   source=" + source.ToString());
        }
    }

在上面的代码中我们在底层StackPanelKeyDown 事件处理函数spLawrence_KeyDown中将事件标记为已处理(e.Handled = true)。这样作为根元素的StackPanelWindowKeyDown 事件处理函数是不会被执行的。事实上如果没有构造函数中的

spMain.AddHandler(UIElement.KeyDownEvent, (KeyEventHandler)spMain_KeyDown, true);

这句代码的确应该是这样,但是通过这句代码作为根元素的StackPanel 注册了事件并标明及时事件被标记为处理依然执行自己的事件处理函数,程序运行后在TextBox中输入一个字符,打印的结果如下:

tbLawrence_KeyDown   sender=System.Windows.Controls.TextBox   source=System.Windows.Controls.TextBox
spLawrence_KeyDown   sender=System.Windows.Controls.StackPanel   source=System.Windows.Controls.TextBox
spMain_KeyDown   sender=System.Windows.Controls.StackPanel   source=System.Windows.Controls.TextBox

可以看到作为根元素的StackPanel 的事件处理函数执行了,但是Window 的事件处理函数没有执行。


参考文章:https://wpf.2000things.com/2012/06/20/584-handling-an-event-that-has-already-been-handled/



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用`addHandler`方法向日志记录器添加处理程序。`addHandler`方法可以用来添加不同类型的处理程序,例如`StreamHandler`、`FileHandler`等,以将日志消息发送到不同的目标。 以下是一个示例,演示如何使用`addHandler`方法将日志消息发送到控制台和文件中: ```python import logging # 创建一个日志记录器 logger = logging.getLogger('my_logger') logger.setLevel(logging.DEBUG) # 创建一个处理程序,并设置日志级别 console_handler = logging.StreamHandler() console_handler.setLevel(logging.INFO) # 创建一个文件处理程序,并设置日志级别 file_handler = logging.FileHandler('mylog.log') file_handler.setLevel(logging.DEBUG) # 定义日志格式 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # 将格式应用于处理程序 console_handler.setFormatter(formatter) file_handler.setFormatter(formatter) # 将处理程序添加到记录器 logger.addHandler(console_handler) logger.addHandler(file_handler) # 记录日志消息 logger.debug('This is a debug message') logger.info('This is an info message') logger.warning('This is a warning message') logger.error('This is an error message') ``` 上述示例中,我们创建了一个名为`my_logger`的日志记录器,并设置了日志级别为`DEBUG`。然后,我们创建了一个发送日志消息到控制台的处理程序`console_handler`,并设置其日志级别为`INFO`。接着,我们创建了一个将日志消息写入文件的处理程序`file_handler`,并设置其日志级别为`DEBUG`。最后,我们将格式化器应用于处理程序,并将处理程序添加到记录器中。 通过调用`logger.debug`、`logger.info`、`logger.warning`和`logger.error`方法,我们可以记录不同级别的日志消息。这些消息将根据处理程序的日志级别进行过滤,并发送到相应的目标(控制台和文件)。 请注意,以上示例只是一个简单的示例,您可以根据实际需求进行调整和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值