路由事件与原先直达式的事件的最大区别就是路由事件更加的自由了,使我们更方便的lu代码
附加事件只是路由事件的一种用法,本质上没有区别,说不定哪天就会被取消这个概念
自定义路由事件
这个事件的用途是报告事件发生的时间
- 首先,我们创建一个 RoutedEventArgs 类的派生类(用途路由事件处理器的参数),
并为其添加 ClickTime属性:
class ReportTimeEventArgs : RoutedEventArgs
{
public ReportTimeEventArgs(RoutedEvent routedEvent,
object source):base(routedEvent,source) { }
public DateTime ClickTime { get; set; }
}
- 创建一个Button的派生类并为其添加路由事件:
class TimeButton : Button
{
public event EventHandler ReportTime
{
add { AddHandler(ReportTimeEvent, value); }
remove { RemoveHandler(ReportTimeEvent, value); }
}
public static readonly RoutedEvent ReportTimeEvent =
EventManager.RegisterRoutedEvent("ReportTime", RoutingStrategy.Bubble, // 冒泡式
typeof(EventHandler<ReportTimeEventArgs>), typeof(TimeButton));
protected override void OnClick()
{
base.OnClick();
ReportTimeEventArgs reportTimeEventArgs =
new ReportTimeEventArgs(ReportTimeEvent, this);
reportTimeEventArgs.ClickTime = DateTime.Now;
this.RaiseEvent(reportTimeEventArgs); // 激发事件
}
}
- 程序界面 XAML代码:
<Grid x:Name="g1" local:TimeButton.ReportTime="ReportTimeHandler">
<Grid x:Name="g2" local:TimeButton.ReportTime="ReportTimeHandler">
<Grid x:Name="g3" local:TimeButton.ReportTime="ReportTimeHandler">
<StackPanel x:Name="s1" local:TimeButton.ReportTime="ReportTimeHandler">
<ListBox x:Name="listBox" Margin="5"/>
<local:TimeButton x:Name="bt1" Width="120" Height="40" Content="报时"
local:TimeButton.ReportTime="ReportTimeHandler"/>
</StackPanel>
</Grid>
</Grid>
</Grid>
- 路由事件处理器:
private void ReportTimeHandler(object sender,ReportTimeEventArgs e)
{
FrameworkElement element = sender as FrameworkElement;
string timeStr = e.ClickTime.ToLongTimeString();
string content = string.Format("{0} 到达 {1}", timeStr, element.Name);
this.listBox.Items.Add(content);
if(element.Name == "g2") // 路由到名称为 g2的 元素时,结束
{
e.Handled = true;
}
}
- 效果演示:
自定义附加事件
设计一个 Student类,点击按钮时捕获这个类的信息
- XAML 界面代码:
<Grid x:Name="gridMain">
<Button x:Name="button1" Content="OK" Width="80" Height="80" Click="Button1_Click"/>
</Grid>
- Student 类:
class Student
{
public static readonly RoutedEvent NameChangedEvent = EventManager.RegisterRoutedEvent(
"MyEvent", RoutingStrategy.Bubble, typeof(EventHandler), typeof(Student));
// Student 类不是 UIElement类的派生类,所以没有 addhandler 和 removehandler方法,
// 所以需要自己进行封装
public static void AddNameChangeHandler(DependencyObject d, RoutedEventHandler h)
{
UIElement e = d as UIElement;
if (e != null)
{
e.AddHandler(Student.NameChangedEvent, h);
}
}
public static void RemoveNameChangeHandler(DependencyObject d, RoutedEventHandler h)
{
UIElement e = d as UIElement;
if (e != null)
{
e.RemoveHandler(Student.NameChangedEvent, h);
}
}
public int Id { get; set; }
public string Name { get; set; }
}
- Click 事件处理器:
private void Button1_Click(object sender, RoutedEventArgs e)
{
Student student = new Student() { Id = 1, Name = "huameng" };
student.Name = "nihao";
RoutedEventArgs args = new RoutedEventArgs(Student.NameChangedEvent, student);
this.button1.RaiseEvent(args);
}
- 路由事件处理器:
private void StudentNameChangedHandler(object sender, RoutedEventArgs e)
{
MessageBox.Show((e.OriginalSource as Student).Name);
}
- MainWindow 构造器中进行路由监听:
Student.AddNameChangeHandler(this.gridMain, StudentNameChangedHandler);
- 效果演示: