刚开始用WPF,总是搞不清三个事件源的关系,经过测试,终于有点明白了:
sender 事件的发送者 说白了就是谁调用的事件处理器
Source事件源 就是谁激发(raise)的事件 不使用路由事件的话 sender跟source是同一对象
OriginalSource 也是事件源 但他与Source不同的地方在于他是原始事件源,真正的激发事件的源头,当没有进行封装的时候,二者是同一对象
从下面这个例子中可以看出明显的区别
1.自定义控件
XAML
<UserControl x:Class="SourceTest.UserControl1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> <Grid> <StackPanel> <Button x:Name="testButton" Content="testButton" Click="testButton_Click" /> </StackPanel> </Grid> </UserControl>
CodeBehind
using System.Windows; using System.Windows.Controls; namespace SourceTest { /// <summary> /// UserControl1.xaml 的交互逻辑 /// </summary> public partial class UserControl1 : UserControl { public UserControl1() { InitializeComponent(); } private void testButton_Click(object sender, RoutedEventArgs e) { MessageBox.Show(string.Format("sender Type:{0} \n\r source Type:{1} \n\r originalSource Type: {2}", sender.GetType().Name,e.Source.GetType().Name, e.OriginalSource.GetType().Name),"子窗体消息"); } } }
2.主窗体
XAML
<Window x:Class="SourceTest.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:SourceTest" Title="MainWindow" Height="100" Width="200"> <Grid> <local:UserControl1 x:Name="test1"/> </Grid> </Window>
CodeBehind
using System.Windows; using System.Windows.Controls; namespace SourceTest { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); this.AddHandler(Button.ClickEvent, new RoutedEventHandler((s, e) => { MessageBox.Show(string.Format("sender Type:{0} \n\r source Type:{1} \n\r originalSource Type {2}", s.GetType().Name, e.Source.GetType().Name, e.OriginalSource.GetType().Name),"主窗体消息"); })); } } }
3.点击按钮 运行结果
这里多说一句,路由事件与传统CLR事件的区别在于,CLR事件的发送者是某个控件,响应者是某个事件处理器,发送者与响应者之间有个明显的订阅关系
路由事件的激发事件的对象跟处理事件的对象是分开的,源只负责激发事件,谁进行处理,他并不关系