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() + ":\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);

}

 

WPF学习之路(四)路由

 可以查看路由事件的线路

 

 

 

 

 

 

To be continue...

你可能感兴趣的:(WPF)