RoutedEventArgs有两个属性:OriginalSource和Source,这两个属性都表示路由事件传递的起点(即事件消息的源头),OriginalSource表示VisualTree上的源头,而Source表示的是LogicalTree上的消息源头。事例如下:
XAML代码:
<UserControl x:Class="MyTest.MyUserControl"
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="80" d:DesignWidth="80">
<Border BorderBrush="Orange" BorderThickness="3" CornerRadius="5">
<Button x:Name="innerButton" Width="80" Height="80" Content="OK"/>
</Border>
</UserControl>
<Grid>
<local:MyUserControl x:Name="myUserControl" Margin="10"/>
</Grid>
C#代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.AddHandler(Button.ClickEvent, new RoutedEventHandler(this.Button_Click));
}
private void Button_Click(object sender, RoutedEventArgs e)
{
string strOrigialSource = string.Format("VisualTree start point: {0}, type is {1}.", (e.OriginalSource as FrameworkElement).Name, e.OriginalSource.GetType().Name);
string strSource = string.Format("LogicalTree start point: {0}, type is {1}.", (e.Source as FrameworkElement).Name, e.Source.GetType().Name);
MessageBox.Show(strOrigialSource + "\r\n" + strSource);
}
}
在WPF事件系统中还有一种事件被称为附加事件(Attached Event),本质就是路由事件。路由事件的宿主都是些拥有可视化实体的界面元素,而附加事件则不具备显示在用户界面上的能力。也就是说,附加事件的宿主没有界面渲染功能,但可以使用附加事件与其他对象进行沟通。实例如下:
XAML代码:
<Grid x:Name="gridMain">
<Button x:Name="button1" Content="OK" Width="80" Height="80" Click="Button_Click"/>
</Grid>
C#代码:
public class Student
{
public static readonly RoutedEvent NameChangedEvent = EventManager.RegisterRoutedEvent("NameChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Student));
public int Id { get; set; }
public string Name { get; set; }
}
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.gridMain.AddHandler(Student.NameChangedEvent, new RoutedEventHandler(this.NameChangedEventHandler));
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Student stu = new Student { Id = 101, Name = "Tom" };
stu.Name = "Tim";
RoutedEventArgs args = new RoutedEventArgs(Student.NameChangedEvent, stu);
this.button1.RaiseEvent(args);
}
private void NameChangedEventHandler(object sender, RoutedEventArgs e)
{
MessageBox.Show((e.OriginalSource as Student).Id.ToString());
}
}
为附加事件添加CLR包装器时,微软规定:
(1)、为目标UI元素添加附加事件侦听器的包装器是一个名为Add*Handler的public static方法,星号代表事件名称。此方法接收两个参数,第一个是事件的侦听者(类型为DependencyObject),第二个参数为事件的处理器(RoutedEventHandler委托类型);
(2)、解除UI元素对附加事件侦听器的包装器是名为Remove*Handler的public static方法,星号亦为事件名称,参数与Add*Handler一致。事例如下:
XAML代码:
<Grid x:Name="gridMain">
<Button x:Name="button1" Content="OK" Width="80" Height="80" Click="Button_Click"/>
</Grid>
C#代码:
public class Student
{
public static readonly RoutedEvent NameChangedEvent = EventManager.RegisterRoutedEvent("NameChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Student));
public static void AddNameChangedEventHandler(DependencyObject d, RoutedEventHandler r)
{
UIElement e = d as UIElement;
if (null != e)
e.AddHandler(Student.NameChangedEvent, r);
}
public static void RemoveNameChangedEventHandler(DependencyObject d, RoutedEventHandler r)
{
UIElement e = d as UIElement;
if (null != e)
e.RemoveHandler(Student.NameChangedEvent, r);
}
public int Id { get; set; }
public string Name { get; set; }
}
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
//this.gridMain.AddHandler(Student.NameChangedEvent, new RoutedEventHandler(this.NameChangedEventHandler));
Student.AddNameChangedEventHandler(this.gridMain, new RoutedEventHandler(this.NameChangedEventHandler));
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Student stu = new Student { Id = 101, Name = "Tom" };
stu.Name = "Tim";
RoutedEventArgs args = new RoutedEventArgs(Student.NameChangedEvent, stu);
this.button1.RaiseEvent(args);
}
private void NameChangedEventHandler(object sender, RoutedEventArgs e)
{
MessageBox.Show((e.OriginalSource as Student).Id.ToString());
}
}
UIElement类是路由事件宿主与附加事件宿主的分水岭。如果在一个非UIElement派生类中注册了路由事件,则这个类的实例既不能自己激发(Raise)此路由事件,也无法自己侦听此路由事件,只能把这个事件的激发"附着"在某个具有RaiseEvent方法的对象上,借助此对象的RaiseEvent方法把事件发送出去;事件的侦听任务也只能交给别的对象去做。
本文出自 “墨池小样儿” 博客,请务必保留此出处http://306702895.blog.51cto.com/8366753/1622876
原文地址:http://306702895.blog.51cto.com/8366753/1622876