📅  最后修改于: 2020-11-18 09:52:21             🧑  作者: Mango
路由事件是一种事件,可以在元素树中的多个侦听器上调用处理程序,而不仅仅是引发该事件的对象。基本上,这是CLR事件,由Routed Event类的实例支持。它已在WPF事件系统中注册。 RoutedEvents具有三种主要的路由策略,如下所示:
直接事件类似于Windows表单中的事件,这些事件是由事件发生的元素引发的。
与标准CLR事件不同,直接路由事件支持类处理,并且可以在自定义控件样式的事件设置器和事件触发器中使用它们。
直接事件的一个很好的例子是MouseEnter事件。
冒泡事件始于事件发生的元素。然后,它沿着视觉树向上移动到视觉树中的最顶层元素。因此,在WPF中,最上面的元素很可能是一个窗口。
调用元素树根上的事件处理程序,然后事件沿视觉树向下传播到所有子节点,直到到达事件发生的元素为止。
冒泡事件与隧道事件之间的区别在于,隧道事件将始终以预览开始。
在WPF应用程序中,事件通常实现为隧道/冒泡对。因此,您将有一个预览MouseDown,然后是MouseDown事件。
下面给出的是路由事件的简单示例,其中创建了一个按钮和三个带有某些属性和事件的文本块。
这是Button,StackPanel和Window的Click事件实现的C#代码。
using System.Windows;
namespace WPFRoutedEvents {
///
/// Interaction logic for MainWindow.xaml
///
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e) {
txt1.Text = "Button is Clicked";
}
private void StackPanel_Click(object sender, RoutedEventArgs e) {
txt2.Text = "Click event is bubbled to Stack Panel";
}
private void Window_Click(object sender, RoutedEventArgs e) {
txt3.Text = "Click event is bubbled to Window";
}
}
}
当您编译并执行上述代码时,它将产生以下窗口-
当您单击按钮时,文本块将得到更新,如下所示。
如果要在任何特定级别停止路由事件,则需要设置e.Handled = true;。
让我们更改StackPanel_Click事件,如下所示-
private void StackPanel_Click(object sender, RoutedEventArgs e) {
txt2.Text = "Click event is bubbled to Stack Panel";
e.Handled = true;
}
当你点击按钮,你会发现,点击事件不会被路由到窗口,将在StackPanel的停止和第三文本块将不会被更新。
在.NET Framework中,还可以定义自定义路由事件。您需要按照下面给出的步骤在C#中定义自定义路由事件。
使用系统调用RegisterRoutedEvent声明并注册您的路由事件。
指定路由策略,即冒泡,隧道或直接。
提供事件处理程序。
让我们以一个示例来了解有关自定义路由事件的更多信息。请按照下面给出的步骤-
使用WPFCustomRoutedEvent创建一个新的WPF项目
右键单击您的解决方案,然后选择添加>新建项目…
将打开以下对话框,现在选择“自定义控件(WPF)”并将其命名为MyCustomControl 。
单击添加按钮,您将看到在解决方案中将添加两个新文件(Themes / Generic.xaml和MyCustomControl.cs)。
以下XAML代码为Generic.xaml文件中的自定义控件设置样式。
下面给出的是MyCustomControl类的C#代码,该类继承自Control类,在Control类中为自定义控件创建了自定义路由事件Click。
using System.Windows;
using System.Windows.Controls;
namespace WPFCustomRoutedEvent {
public class MyCustomControl : Control {
static MyCustomControl() {
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl),
new FrameworkPropertyMetadata(typeof(MyCustomControl)));
}
public override void OnApplyTemplate() {
base.OnApplyTemplate();
//demo purpose only, check for previous instances and remove the handler first
var button = GetTemplateChild("PART_Button") as Button;
if (button ! = null)
button.Click + = Button_Click;
}
void Button_Click(object sender, RoutedEventArgs e) {
RaiseClickEvent();
}
public static readonly RoutedEvent ClickEvent =
EventManager.RegisterRoutedEvent("Click", RoutingStrategy.Bubble,
typeof(RoutedEventHandler), typeof(MyCustomControl));
public event RoutedEventHandler Click {
add { AddHandler(ClickEvent, value); }
remove { RemoveHandler(ClickEvent, value); }
}
protected virtual void RaiseClickEvent() {
RoutedEventArgs args = new RoutedEventArgs(MyCustomControl.ClickEvent);
RaiseEvent(args);
}
}
}
这是C#中的自定义路由事件实现,当用户单击它时将显示一个消息框。
using System.Windows;
namespace WPFCustomRoutedEvent {
//
// Interaction logic for MainWindow.xaml
//
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void MyCustomControl_Click(object sender, RoutedEventArgs e) {
MessageBox.Show("It is the custom routed event of your custom control");
}
}
}
这是MainWindow.xaml中的实现,用于添加具有路由事件Click的自定义控件。
编译并执行上述代码后,将产生以下窗口,其中包含一个自定义控件。
当您单击自定义控件时,它将产生以下消息。