WPF MVVM模式下路由事件
一,路由事件下三种路由策略:
1 冒泡:由事件源向上传递一直到根元素。2直接:只有事件源才有机会响应事件。3隧道:从元素树的根部调用事件处理程序并依次向下深入直到事件源。一般情况下,WPF提供的输入事件都是以隧道/冒泡对实现的。隧道事件常常被称为Preview事件。
二,MVVM简单的路由注册事件
.CS
public class MainViewModel : ViewModelBase { public MainViewModel() {
//这里使用了Preview事件 EventManager.RegisterClassHandler(typeof(Grid), Grid.PreviewMouseLeftButtonDownEvent, new RoutedEventHandler(OnClick)); } void OnClick(object sender, RoutedEventArgs e) { if (e.Source is Button) { MessageBox.Show($"{Grid.GetRow((e.Source as Button))}:{(e.Source as Button).Name}" ); } } }
.XAML
<Grid > <Grid.RowDefinitions> <RowDefinition Height="50"></RowDefinition> <RowDefinition Height="50"></RowDefinition> <RowDefinition Height="50"></RowDefinition> </Grid.RowDefinitions> <Button x:Name="Grid1" Width="50" HorizontalContentAlignment="Center" >1</Button> <Button Grid.Row="1" x:Name="Grid2" Width="50" >2</Button> </Grid>
效果
三,自定义路由事件
1,创建一个BottonV类
class BottonV:Button { //第一步:声明并注册【路由事件】 //EventManager.RegisterRoutedEvent(CLR事件包装器名称,路由事件冒泡策略,事件处理程序的类型,路由事件的所有者类类型) public static readonly RoutedEvent OpenEvent = EventManager.RegisterRoutedEvent("Open", RoutingStrategy.Bubble, typeof(EventHandler<CustomRouting>), typeof(BottonV)); //第二步:为路由事件添加CLR事件包装器 public event RoutedEventHandler Open { //为指定的路由事件添加路由事件处理程序,并将该处理程序添加到当前元素的处理程序集合中。 add { this.AddHandler(OpenEvent, value); } remove { this.RemoveHandler(OpenEvent, value); } } //第三步:激发路由事件 protected override void OnClick() { base.OnClick(); //创建事件携带信息(RoutedEventArgs类实例),并和路由事件关联 CustomRouting args = new CustomRouting(OpenEvent, this); args.EventTime = DateTime.Now; //调用元素的RaiseEvent方法(继承自UIElement类),引发路由事件 this.RaiseEvent(args); } }
2,定义一个路由
/// <summary> /// 继承RoutedEventArgs /// </summary> public class CustomRouting:RoutedEventArgs { public CustomRouting(RoutedEvent routedEvent, object source) : base(routedEvent, source) { } public DateTime EventTime { get; set; } }
3,MainWindow页面创建一个路由事件
private void TimeButton_ReportTime(object sender, CustomRouting e)//注意参数 { MessageBox.Show(e.EventTime.ToLongTimeString() + (sender as FrameworkElement).Name); }
效果如下: