You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:41:19