一、概念
消息层层传递,遇到安装有事件侦听器的对象,通过事件处理器响应事件,并决定事件是否继续传递;
二、自定义路由器事件
主要步骤:(与依赖属性相似)
1、声明并注册路由事件;
2、为路由事件添加CLR事件包装器;
3、创建可以激发路由事件的方法;
1、使用EventManager.RegisterRoutedEvent注册路由事件
public static readonly RoutedEvent DisplayTimeEvent = EventManager.RegisterRoutedEvent(
"DisplayTime",
RoutingStrategy.Bubble,
typeof(EventHandler<DisPlayTimeHanderArgs>),
typeof(TimeButton));
参数一:路由器名称,与CLR事件包装器名称一致;
参数二:路由事件策略:
Bubble冒泡式:UI树自底端(事件激发)向顶端传递
Tunnel隧道式:树根向事件激发控件传递,与冒泡相反
Direct直达式:模仿CLR直接事件
参数三:指定事件处理器的类型,标签与此参数委托一致;
参数四:指明路由事件的宿主;
RoutedEventArgs常用属性:
Handled,bool类型,为true。不再传递;
Source:表示LogicalTree上的消息源头(传递起点);
OriginalSource:VisualTree上的源头;
2、添加包装器
public event RoutedEventHandler DisplayTime
{
add
{
AddHandler(DisplayTimeEvent, value);
}
remove
{
RemoveHandler(DisplayTimeEvent, value);
}
}
3、激发事件的方法
protected override void OnClick()
{
base.OnClick();
DisPlayTimeHanderArgs timeHanderArgs = new DisPlayTimeHanderArgs(DisplayTimeEvent, this);
timeHanderArgs.Time=DateTime.Now;
this.RaiseEvent(timeHanderArgs);
}
示例代码:
public class TimeButton : Button
{
public event RoutedEventHandler DisplayTime
{
add
{
AddHandler(DisplayTimeEvent, value);
}
remove
{
RemoveHandler(DisplayTimeEvent, value);
}
}
public static readonly RoutedEvent DisplayTimeEvent = EventManager.RegisterRoutedEvent(
"DisplayTime",
RoutingStrategy.Bubble,
typeof(EventHandler<DisPlayTimeHanderArgs>),
typeof(TimeButton));
protected override void OnClick()
{
base.OnClick();
DisPlayTimeHanderArgs timeHanderArgs = new DisPlayTimeHanderArgs(DisplayTimeEvent, this);
timeHanderArgs.Time = DateTime.Now;
this.RaiseEvent(timeHanderArgs);
}
}
public class DisPlayTimeHanderArgs : RoutedEventArgs
{
public DisPlayTimeHanderArgs(RoutedEvent routed, object source) : base(routed, source)
{
}
public DateTime Time { get; set; }
}
}
界面代码:
<Grid>
<model:TimeButton x:Name="tbtn" Width="80" Height="80" Background="LightBlue" Content="Time"/>
</Grid>
主窗口后台代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.tbtn.AddHandler(TimeButton.DisplayTimeEvent, new RoutedEventHandler(DisplayTimeHander));
}
private void DisplayTimeHander(object sender,RoutedEventArgs e)
{
FrameworkElement frameworkElement = sender as FrameworkElement;
DisPlayTimeHanderArgs args = e as DisPlayTimeHanderArgs;
MessageBox.Show(frameworkElement.Name.ToString()+"\r\n"+ args.Time.ToShortTimeString());
}
}
三、附加事件
附加事件是路由事件的一种,但不具备显示在用户界面上的能力,一般存在Binding类、Mouse类、KeyBoard类
注意:非UIElement的派生类,不具有RaiseEvent方法,通过借用其它控件的RaiseEvent发送事件,同理没有AddHandler和RemoveHandler方法,所以通过”借用“的方式为事件进行包装;
示例代码:
internal class Student
{
public int Id { get; set; }
public string Name { get; set; }
public static void AddAttanchedHandler(DependencyObject dpo, RoutedEventHandler e)
{
UIElement uIElement = dpo as UIElement;
if (uIElement != null)
{
uIElement.AddHandler(AttanchedEvent, e);
}
}
public static void RemoveAttanchedHandler(DependencyObject dpo, RoutedEventHandler e)
{
UIElement uIElement = dpo as UIElement;
if (uIElement != null)
{
uIElement.RemoveHandler(AttanchedEvent, e);
}
}
public static readonly RoutedEvent AttanchedEvent =
EventManager.RegisterRoutedEvent("Attanched", RoutingStrategy.Bubble, typeof(RoutedEventArgs), typeof(Student));
}
主窗口后台:
public MainWindow()
{
InitializeComponent();
sp.AddHandler(Student.AttanchedEvent, new RoutedEventHandler(AttanchedHandler));
Student.AddAttanchedHandler(this.grd, new RoutedEventHandler(AttanchedHandler));
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Student student = new Student() { Id = 1, Name = "Tom" };
student.Name = "Auston";
RoutedEventArgs args = new RoutedEventArgs(Student.AttanchedEvent,student);
btn.RaiseEvent(args);
}
private void AttanchedHandler(object sender,RoutedEventArgs e)
{
FrameworkElement frameworkElement = sender as FrameworkElement;
listbox.Items.Add(frameworkElement.Name+"\t"+(e.OriginalSource as Student).Name);
}
Xaml代码:
<Grid x:Name="grd" >
<StackPanel Name="sp">
<ListBox Name="listbox"/>
<Button Width="80" Name="btn" Height="80" Background="LightGray" Content="OK" Click="Button_Click"/>
</StackPanel>
</Grid>
四、附:部分代码段(snippet)
可添加进代码片段管理器,提升工作效率
路由器事件代码段:
public event $type$ $event$
{
add
{
AddHandler($event$Event, value);
}
remove
{
RemoveHandler($event$Event, value);
}
}
//Register a RoutedEvent....
public static readonly RoutedEvent $event$Event =
EventManager.RegisterRoutedEvent("$event$", RoutingStrategy.Bubble, typeof(RoutedEventArgs), typeof($owner$));
附加事件代码段:
public static void Add$event$Handler(DependencyObject dpo, RoutedEventHandler e)
{
UIElement uIElement = dpo as UIElement;
if (uIElement != null)
{
uIElement.AddHandler($event$Event, e);
}
}
public static void Remove$event$Handler(DependencyObject dpo, RoutedEventHandler e)
{
UIElement uIElement = dpo as UIElement;
if (uIElement != null)
{
uIElement.RemoveHandler($event$Event, e);
}
}
//Register a Attanched Event...
public static readonly RoutedEvent $event$Event =
EventManager.RegisterRoutedEvent("$event$", RoutingStrategy.Bubble, typeof(RoutedEventArgs), typeof($owner$));