你的位置:首页 > ASP.net教程

[ASP.net教程]WPF学习之路(四)路由


路由事件概述

功能定义:路由事件是一种可以针对元素树中的多个侦听器(而不是仅针对引发该事件的对象)调用处理程序的事件。

实现定义:路由事件是一个 CLR 事件,可以由RouteEvent 类的实例提供支持并由 Windows Presentation Foundation (WPF) 事件系统来处理。

 

实例:

Xaml

<Border Height="50" Width="300" BorderBrush="Gray" BorderThickness="1"> <StackPanel Background="LightGray" Orientation="Horizontal" Button.Click="CommonClickHandler">  <Button Name="YesButton" Width="Auto" >Yes</Button>  <Button Name="NoButton" Width="Auto" >No</Button>  <Button Name="CancelButton" Width="Auto" >Cancel</Button> </StackPanel></Border>

在这个简化的元素树中,Click事件的源是某个 Button元素,而所单击的 Button是有机会处理该事件的第一个元素。 但是,如果附加到 Button的任何处理程序均未作用于该事件,则该事件将向上冒泡到元素树中的 Button父级(即 StackPanel)。 该事件可能会冒泡到 Border,然后会到达元素树的页面根(未显示出来)。

换言之,此Click事件的事件路由为:Button-->StackPanel-->Border-->...

 

路由事件的策略

Bubbling:路由事件随后会路由到后续的父元素,直到到达元素树的根。 

Direct:只有源元素本身才有机会调用处理程序以进行响应

Tunneling:最初将在元素树的根处调用事件处理程序。

路由事件策略会因为一下因素改变:

 

事件处理函数

public delegate void RoutedEventHandler(Object Sender, RoutedEventArgs e);
public delegate void MouseEventHandler(Object Sender, MouseEventArgs e);

RoutedEventArgs和MouseEventArgs包含路由事件的信息

如果设置"Handled"属性为True,路由事件会停止传递

 

类和实例事件处理函数

事件处理函数有两种类型,前一种是普通事件处理函数,"实例事件处理函数",另一种是通过EventManager.RegisterClassHandler方法将一个事件处理函数和类关联起来,"类事件处理函数",优先级更高

 

 

实例:(取自《葵花宝典--WPF自学手册》6.5)

自定义Button类

public class MySimpleButton : Button{  static MySimpleButton()  {    EventManager.RegisterClassHandler(typeof(MySimpleButton), CustomClickEvent, new RoutedEventHandler(CustomClickClassHandler), false);  }  public event EventHandler ClassHandlerProcessed;  public static void CustomClickClassHandler(Object sender, RoutedEventArgs e)  {    MySimpleButton simpBtn = sender as MySimpleButton;    EventArgs args = new EventArgs();    simpBtn.ClassHandlerProcessed(simpBtn, e);  }  //Create and register routed event, routing strategies: Bubble  public static readonly RoutedEvent CustomClickEvent = EventManager.RegisterRoutedEvent(    "CustomClick",    RoutingStrategy.Bubble,    typeof(RoutedEventHandler),    typeof(MySimpleButton));  //CLR event wrapper  public event RoutedEventHandler CustomClick  {    add { AddHandler(CustomClickEvent, value); }    remove { RemoveHandler(CustomClickEvent, value); }  }  //Raise CustomClickEvent  void RaiseCustomClickEvent()  {    RoutedEventArgs newEventArgs = new RoutedEventArgs(MySimpleButton.CustomClickEvent);    RaiseEvent(newEventArgs);  }  //Onclick  protected override void OnClick()  {    RaiseCustomClickEvent();  }}

 

MainWindow.xaml

<Window x:Class="Alex_WPFAPPDemo02.MainWindow"    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    ="http://schemas.microsoft.com/winfx/2006/xaml"    ="clr-namespace:Alex_WPFAPPDemo02"    custom:MySimpleButton.CustomClick="InsertList"    Title="MainWindow" Height="350" Width="525">  <Grid Margin="3" custom:MySimpleButton.CustomClick="InsertList" Name="Grid1">    <Grid.RowDefinitions>      <RowDefinition Height="Auto" />      <RowDefinition Height="*" />      <RowDefinition Height="Auto" />      <RowDefinition Height="Auto" />    </Grid.RowDefinitions>    <custom:MySimpleButton x:Name="simpBtn" CustomClick="InsertList">      My Simple Button    </custom:MySimpleButton>    <ListBox Margin="5" Name="listBox" Grid.Row="1" />    <CheckBox Margin="5" Grid.Row="2" Name="chkHandle">      Handle first event    </CheckBox>    <Button Grid.Row="3" HorizontalAlignment="Right" Margin="5" Padding="3" Click="clear">      Clear List    </Button>  </Grid></Window>

 

MainWindow.xaml.cs

protected int eventCounter = 0;private void InsertList(object sender, RoutedEventArgs e){  eventCounter++;  string message = "#" + eventCounter.ToString() + ":\r\n"    + "InsertList\r\n"    + " Sender: " + sender.ToString() + "\r\n"    + " Source: " + e.Source + "\r\n"    + "Original Source: " + e.OriginalSource;  listBox.Items.Add(message);  e.Handled = (bool)chkHandle.IsChecked;}private void clear(object sender, RoutedEventArgs e){  eventCounter = 0;  listBox.Items.Clear();}

 

添加类处理函数

static MySimpleButton(){  EventManager.RegisterClassHandler(typeof(MySimpleButton), CustomClickEvent, new RoutedEventHandler(CustomClickClassHandler), false);}public event EventHandler ClassHandlerProcessed;public static void CustomClickClassHandler(Object sender, RoutedEventArgs e){  MySimpleButton simpBtn = sender as MySimpleButton;  EventArgs args = new EventArgs();  simpBtn.ClassHandlerProcessed(simpBtn, e);}

 

完善代码

public MainWindow(){  InitializeComponent();  this.simpBtn.ClassHandlerProcessed += new EventHandler(ButtonRaisedClass);}private void ButtonRaisedClass(object sender, EventArgs e){  eventCounter++;  string message = "#" + eventCounter.ToString() + ":\r\n"    + "Windows Class Handler\r\n"    + " Sender: " + sender.ToString();  listBox.Items.Add(message);}private void ProcessHanldersToo(Object sender, RoutedEventArgs e){  eventCounter++;  string message = "#" + eventCounter.ToString() + ":\r\n"    + "ProcessHanldersToo\r\n"    + " Sender: " + sender.ToString()    + " Source: " + e.Source + "\r\n"    + "Original Source: " + e.OriginalSource;  listBox.Items.Add(message);}private void Window_Loaded(object sender, RoutedEventArgs e){  Grid1.AddHandler(MySimpleButton.CustomClickEvent, new RoutedEventHandler(ProcessHanldersToo), true);}

 

 可以查看路由事件的线路

 

 

 

 

 

 

To be continue...