zoukankan      html  css  js  c++  java
  • 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"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:custom="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() + ":
    "
            + "InsertList
    "
            + " Sender: " + sender.ToString() + "
    "
            + " Source: " + e.Source + "
    "
            + "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() + ":
    "
            + "Windows Class Handler
    "
            + " Sender: " + sender.ToString();
        listBox.Items.Add(message);
    }
    
    private void ProcessHanldersToo(Object sender, RoutedEventArgs e)
    {
        eventCounter++;
        string message = "#" + eventCounter.ToString() + ":
    "
            + "ProcessHanldersToo
    "
            + " Sender: " + sender.ToString()
            + " Source: " + e.Source + "
    "
            + "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...

  • 相关阅读:
    【转】多线程:深入了解线程同步lock,Monitor,Mutex,同步事件和等待句柄(中)
    Mono初接触
    计算机颜色格式( 8位 16位 24位 32位色)
    我爱源代码
    Linux小白教程: tar的几种常用格式
    Linux小白教程:查看当前Linux的发行版本、内核(kernel)版本
    10大糟糕预测:
    一日编程小悟
    Linux小白教程:vi(shell文本编辑器)保存、退出命令
    C结构体中的函数指针与函数
  • 原文地址:https://www.cnblogs.com/alex09/p/4432001.html
Copyright © 2011-2022 走看看