我目前正在试验 C# WPF 自定义路由事件,我遇到了一个问题。这就是我想做的:我想从我的主窗口触发一个自定义路由事件,该事件通过堆栈面板隧道传输到由 Button 类派生的自定义控件。然后,自定义控件处理路由事件。
我的问题是当我触发事件时,处理程序从未被调用。
我的代码:
public partial class MainWindow : Window
{
public static readonly RoutedEvent MyRoutedEvent = EventManager.RegisterRoutedEvent("MyRoutedEvent", RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(UIElement));
public static void AddMyRoutedEventHandler(DependencyObject d, RoutedEventHandler handler)
{
UIElement uie = d as UIElement;
if (uie != null)
{
uie.AddHandler(MainWindow.MyRoutedEvent, handler);
}
}
public static void RemoveMyRoutedEventHandler(DependencyObject d, RoutedEventHandler handler)
{
UIElement uie = d as UIElement;
if (uie != null)
{
uie.RemoveHandler(MainWindow.MyRoutedEvent, handler);
}
}
public MainWindow()
{
InitializeComponent();
}
private void keyClassButton1_MyRoutedEvent(object sender, RoutedEventArgs e)
{
Console.Write("nMyRoutedEvent!");
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
RoutedEventArgs newEventArgs = new RoutedEventArgs(MyRoutedEvent, this);
RaiseEvent(newEventArgs);
}
}
XAML 代码:
<Window x:Class="RoutedEvent_Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:RoutedEvent_Test"
Title="MainWindow" Height="350" Width="525" MouseDown="Window_MouseDown">
<Grid>
<StackPanel Name="stackPanel1">
<local:KeyClass x:Name="keyClass1" Content="key class button" Height="30" local:MainWindow.MyRoutedEvent="keyClassButton1_MyRoutedEvent"></local:KeyClass>
</StackPanel>
</Grid>
</Window>
我自己想通了:尽管我已经阅读了一千遍,但它在MSDN描述中清楚地指出:
隧道:最初,元素树根中的事件处理程序是 调用。然后,路由事件通过连续的 沿路由的子元素,朝向节点元素,即 路由事件源(引发路由事件的元素)。 [...]
我对隧道路由事件的第一个想法是:我从主窗口触发一个事件,它通过堆栈面板到达按钮元素。而是:你必须已经从按钮触发它 - 然后它从根元素(主窗口)开始,并通过控制层到达首先触发事件的按钮元素。
我所做的是:我从主窗口触发了事件,这样它就不能去其他任何地方。
此注册似乎不正确:
public static readonly RoutedEvent MyRoutedEvent = EventManager.RegisterRoutedEvent("MyRoutedEvent", RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(UIElement));
您需要在此处注册时将public event ReoutedEventHandler MyRoutedEvent
添加到课程中。这应该是非静态类实例级别处理程序。我在你的代码上看不到它。
你需要在主窗口上需要这样的东西:
public event RoutedEventHandler MyRoutedEvent;
请参阅此处的 MSDN 示例。