根据this MSDN article(以及其他),
在任何实例侦听器处理程序之前调用类处理程序 每当路由事件时,它都附加到该类的实例 到达路线中的元素实例。
我对RoutedEvent
很新,所以我的代码中可能存在错误,但似乎附加到RoutedEvent
的类处理程序被声明为{在附加到同一事件的实例处理程序之前, not 总是会触发。
在下面的示例中,我创建了一个RoutingStrategy.Tunnel
控件类,其中包含隧道TouchButton
和冒泡RoutedEvent
。我为每个人注册了类处理程序。然后,我在窗口中创建了一个类的实例,并处理后面代码中的每个事件。我在类元素和包含它的RoutedEvent
上附加了隧道事件的相同处理程序。所有四个处理程序都在Grid
中显示其名称,以便您可以清楚地看到执行顺序。
这意味着如果我在类MessageBox
事件处理程序中调用e.Handled = true;
,我可以阻止执行到达所有其他事件处理程序,除了附加到PreviewTouch
元素的事件处理程序。这应该是这样的,还是我在某个地方犯了错误?否则,如何阻止执行到达每个实例事件处理程序?
这是班级:
Grid
以下是窗口代码中的实例处理程序:
public class TouchButton : Button
{
static TouchButton()
{
EventManager.RegisterClassHandler(typeof(TouchButton), PreviewTouchEvent,
new RoutedEventHandler(TouchButton_PreviewTouch), true);
EventManager.RegisterClassHandler(typeof(TouchButton), TouchEvent,
new RoutedEventHandler(TouchButton_Touch), true);
}
private static void TouchButton_PreviewTouch(object sender, RoutedEventArgs e)
{
MessageBox.Show("Class TouchButton_PreviewTouch");
}
private static void TouchButton_Touch(object sender, RoutedEventArgs e)
{
MessageBox.Show("Class TouchButton_Touch");
}
public static RoutedEvent TouchEvent = EventManager.RegisterRoutedEvent("Touch",
RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TouchButton));
public event RoutedEventHandler Touch
{
add { AddHandler(TouchEvent, value); }
remove { RemoveHandler(TouchEvent, value); }
}
public static RoutedEvent PreviewTouchEvent = EventManager.RegisterRoutedEvent(
"PreviewTouch", RoutingStrategy.Tunnel, typeof(RoutedEventHandler),
typeof(TouchButton));
public event RoutedEventHandler PreviewTouch
{
add { AddHandler(PreviewTouchEvent, value); }
remove { RemoveHandler(PreviewTouchEvent, value); }
}
protected override void OnClick()
{
RaiseTouchEvent();
}
private void RaiseTouchEvent()
{
RoutedEventArgs touchEventArgs = new RoutedEventArgs(PreviewTouchEvent);
RaiseEvent(touchEventArgs);
if (!touchEventArgs.Handled) RaiseEvent(new RoutedEventArgs(TouchEvent));
}
}
这是控件XAML:
private void TouchButton_PreviewTouch(object sender, RoutedEventArgs e)
{
MessageBox.Show(string.Format("{0} Instance PreviewTouch",
((FrameworkElement)sender).Name));
}
private void TouchButton_Touch(object sender, RoutedEventArgs e)
{
MessageBox.Show(string.Format("{0} Instance Touch",
((FrameworkElement)sender).Name));
}
我确实理解隧道事件是由<Grid Name="Grid" Controls:TouchButton.PreviewTouch="TouchButton_PreviewTouch">
<Controls:TouchButton x:Name="TouchButton" Width="200" Height="45" FontSize="24"
Content="Touch me" Touch="TouchButton_Touch" PreviewTouch="TouchButton_PreviewTouch" />
</Grid>
元素在'隧道'到Grid
元素之前处理的,但我认为类处理程序总是应该在实例处理程序之前触发。如果没有,我怎么能实现这个目标?
更新&gt;&gt;&gt;
感谢@ sanguine的回答,我设法找到一种方法来阻止所有实例处理程序处理事件。如果不是将TouchButton
的声明类处理类型替换为TouchButton
作为乐观建议,而是将其替换为Grid
,那么它将捕获所有FrameworkElement
派生的控件。< / p>
FrameworkElement
答案 0 :(得分:0)
MSDN文章的意思是 - 当遍历事件找到一个元素(在树中)时,它提供了Class和实例处理程序,然后它在实例处理程序之前调用类处理程序。因此,在这种情况下,当事件被触发并从一个隧道传输到in时,它会遇到网格,但Grid类没有任何类处理程序,因此它只调用“Grid”实例使用的实例处理程序。如果在切换按钮中添加此行 -
EventManager.RegisterClassHandler(typeof( Grid ),PreviewTouchEvent, new RoutedEventHandler(TouchButton_PreviewTouch),true);
然后在Grid的实例处理程序之前,将调用相应的类处理程序。