RoutedEventArgs.OriginalSource计算逻辑及实测不符问题咨询
关于WPF中RoutedEventArgs的sender、Source、OriginalSource的疑问解答
先帮你把三个概念的准确含义再理清楚,然后针对你遇到的Button示例异常情况说明原因:
核心概念确认
首先明确这三个属性的官方定义和实际行为:
- sender:完全符合你的理解——就是你把事件处理程序绑定上去的那个元素,在你的代码里就是
sp(StackPanel),因为你是在StackPanel上注册的Button.Click事件处理程序。 - e.Source:路由事件传播时的「逻辑触发源」,也就是从逻辑层面上,哪个元素触发了这个事件。比如点击按钮时,不管按钮内部有什么可视化元素,逻辑上都是这个Button触发了Click事件,所以Source就是Button本身。
- e.OriginalSource:这个是通过命中测试得到的最底层可视化元素,但这里有个容易被忽略的点:它只对底层输入事件(比如
MouseLeftButtonDown、MouseMove)完全生效,而像Click这种控件封装的逻辑事件,控件内部会对这个属性做调整。
你的示例异常原因分析
你遇到的点击btn3里的蓝色Rectangle(r)时,OriginalSource却是btn3的情况,本质是因为Button.Click事件是WPF Button控件封装的逻辑事件,不是底层输入事件:
WPF的Button控件有自己的默认模板,内部会处理底层的鼠标事件(比如MouseLeftButtonDown、MouseLeftButtonUp),当它检测到完整的点击动作(按下+抬起)时,会主动发起一个Click路由事件。在这个过程中,Button会把Click事件的OriginalSource设置为自己——因为Click事件的设计目的是让开发者关注「按钮被点击」这个逻辑行为,而不是按钮内部具体哪个可视化元素被点到了。
如果你想验证这个逻辑,可以给Rectangle添加一个MouseLeftButtonDown事件处理程序,你会看到这个事件的OriginalSource确实是r,这说明底层命中测试是正确的,只是Button的Click事件把这个值做了调整。
如何获取真正的底层命中元素
如果在Click事件里你确实需要知道到底点到了Button内部的哪个元素,可以用Mouse.DirectlyOver属性,它会返回当前鼠标指针下方的最顶层可视化元素:
private void Handler(object sender, RoutedEventArgs e) { var actualHitElement = Mouse.DirectlyOver; // 点击Rectangle时,actualHitElement就是r;点击Button空白区域时就是btn3 }
内容的提问来源于stack exchange,提问作者silviubogan
相关产品推荐
相关产品推荐

