(一)使用WPF内置路由事件

xaml:

 <Window x:Class="WpfApplication1.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-namespace:WpfApplication1"
         Title="Simple Binding" Height="200" Width="200">
     <Grid x:Name="gridRoot" Background="Lime" ButtonBase.Click="ButtonClicked">
         <Grid x:Name="gridA" Margin="10" Background="Blue">
             <Grid.ColumnDefinitions>
                 <ColumnDefinition/>
                 <ColumnDefinition/>
             </Grid.ColumnDefinitions>
             <Canvas x:Name="canvasLeft" Grid.Column="0" Background="Red" Margin="10">
                 <Button x:Name="buttonLeft" Content="Left" Width="40" Height="100" Margin="10"/>
             </Canvas>
             <Canvas x:Name="canvasRight" Grid.Column="1" Background="Yellow" Margin="10">
                 <Button x:Name="buttonRight" Content="Right" Width="40" Height="100" Margin="10"/>
             </Canvas>
         </Grid>
     </Grid>
 </Window>

xaml.cs:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Data;
 using System.Windows.Documents;
 using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using System.Windows.Navigation;
 using System.Windows.Shapes;
 using System.Data;
 using MySql.Data;
 using MySql.Data.Entity;
 using MySql.Data.MySqlClient;
 using System.Xml;
 using System.Xml.Linq;
 using System.IO;

 namespace WpfApplication1
 {
     /// <summary>
     /// Interaction logic for MainWindow.xaml
     /// </summary>
     public partial class MainWindow : Window
     {
         public MainWindow()
         {
             InitializeComponent();
             //this.gridRoot.AddHandler(Button.ClickEvent, new RoutedEventHandler(this.ButtonClicked));
         }
         private void ButtonClicked(object sender, RoutedEventArgs e)
         {
             MessageBox.Show((e.OriginalSource as FrameworkElement).Name);
         }
     }
 }

这里的时间从底层冒泡上去到gridRoot处侦听到该时间,才MessageBox.Show出来

(二)自定义路由事件

书上的例子有问题,不能通过

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Data;
 using System.Windows.Controls;

 namespace WpfApplication1
 {
     class TimeButton : Button
     {
         public static readonly RoutedEvent ReportTimeEvent = EventManager.RegisterRoutedEvent
             ("ReportTime", RoutingStrategy.Bubble, typeof(EventHandler<ReportTimeEventArgs>), typeof(TimeButton));

         public event RoutedEventHandler ReportTime
         {
             add { this.AddHandler(ReportTimeEvent, value); }
             remove { this.RemoveHandler(ReportTimeEvent, value); }
         }

         protected override void OnClick()
         {
             base.OnClick();
             ReportTimeEventArgs args = new ReportTimeEventArgs(ReportTimeEvent, this);
             args.ClickTime = DateTime.Now;
             this.RaiseEvent(args);
         }

     }
 }
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.Windows;

 namespace WpfApplication1
 {
     class ReportTimeEventArgs : RoutedEventArgs
     {
         public ReportTimeEventArgs(RoutedEvent routedEvent, object source)
             : base(routedEvent, source) { }
         public DateTime ClickTime { get; set; }
     }
 }
 <Window x:Class="WpfApplication1.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-namespace:WpfApplication1"
         Title="Simple Binding" x:Name="window_1" Height="300" Width="300"
         local:TimeButton.ReportTime="ReportTimeHandler">
     <Grid x:Name="grid_1" local:TimeButton.ReportTime="ReportTimeHandler">
         <Grid x:Name="grid_2" local:TimeButton.ReportTime="ReportTimeHandler">
             <Grid x:Name="grid_3" local:TimeButton.ReportTime="ReportTimeHandler">
                 <StackPanel x:Name="stackPanel_1"
                         local:TimeButton.ReportTime="ReportTimeHandler">
                     <ListBox x:Name="listBox"/>
                     <local:TimeButton x:Name="timeButton" Width="80" Height="80"
                                       Content="报时" local:TimeButton.ReportTime="ReportTimeHandler"/>
                 </StackPanel>
             </Grid>
         </Grid>
     </Grid>
 </Window>
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Data;
 using System.Windows.Documents;
 using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using System.Windows.Navigation;
 using System.Windows.Shapes;
 using System.Data;
 using MySql.Data;
 using MySql.Data.Entity;
 using MySql.Data.MySqlClient;
 using System.Xml;
 using System.Xml.Linq;
 using System.IO;

 namespace WpfApplication1
 {
     /// <summary>
     /// Interaction logic for MainWindow.xaml
     /// </summary>
     public partial class MainWindow : Window
     {
         public MainWindow()
         {
             InitializeComponent();
             //this.gridRoot.AddHandler(Button.ClickEvent, new RoutedEventHandler(this.ButtonClicked));
         }
         private void ReportTimeHander(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);
         }
     }
 }
04-03 16:03