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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值