路由事件隧道不会到达子元素

5

我发现有很多关于冒泡的示例,但没有关于事件隧道的说明。这里是关于事件隧道的示例,例如从父级到子级传递事件。我认为我的主要问题在于不理解如何在子控件(WindowControl到UserControl)中注册路由事件。

public partial class MyParent : UserControl
{
  public static readonly RoutedEvent RoutedMouseUpEvent = EventManager.RegisterRoutedEvent(
        "PreviewMouseLeftButtonUp", RoutingStrategy.Tunnel, typeof(RoutedEventHandler),   typeof(WindowControl)); 

// Provide CLR accessors for the event        
public event RoutedEventHandler MouseUp
{
  add { AddHandler(RoutedMouseUpEvent, value); }
  remove { RemoveHandler(RoutedMouseUpEvent, value); }
}

public addView(UserControl view)
{
WindowControl win = new WindowControl();
win.Content = view;
}

private void Grid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
  RoutedEventArgs newEventArgs = new RoutedEventArgs(MyParent.RoutedMouseUpEvent);
            RaiseEvent(newEventArgs);
}
}

封装addView是必要的,应该没有问题?子项是通过addView添加的。 Grid_MouseLeftButtonUp被调用。 接收器看起来像这样(它是mvvm所以没有太多内容):

public partial class ChildView : UserControl
{
 void UserControl_PreviewMouseLeftButtonUp(object sender, RoutedEventArgs args)
 {
    int i = 0; // The breakpoint is never called
 }
}

在XAML中。
<Grid>
   <Border BorderBrush="black" BorderThickness="1" HorizontalAlignment="Center"   VerticalAlignment="Center" PreviewMouseLeftButtonUp="UserControl_PreviewMouseLeftButtonUp">
</Border>
</Grid>

如果我遗漏了什么,请告诉我。 问题是,路由事件无法到达UserControl_PreviewMouseLeftButtonUp。

1个回答

11

这不是隧道路由策略的工作原理。 隧道意味着事件将从根开始,沿着树路径向下传递到调用控件。 例如,如果我们有以下可视化树

Window
|
|--> SomeUserControl
|--> MyParent
     |
     |--> ChildView

如果MyParent引发了一个事件,那么事件将会按照隧道事件的顺序访问:

  1. Window
  2. MyParent

不会按照冒泡事件的顺序访问:

  1. MyParent
  2. ChildView

因此总结一下,冒泡事件始终从引发事件的控件开始并在可视树的根节点结束,而隧道事件则从可视树的根节点开始并在引发事件的控件结束(完全相同的路径,只是顺序相反)。

编辑:您可以在MSDN的路由事件概述中了解更多关于路由事件的信息。它还有一个很好的图片来演示这一点:

enter image description here


我不明白。为什么我不能告诉程序MyParent是根节点呢? - Martin
2
现在我明白了。隧道无法到达我的子级,这使得它在我看来相当无用。我确实阅读了那些文档,但不知何故没有以这种方式理解它。我将使用接口和简单传递数据来解决我的问题(这是计划B)。非常感谢您的出色解释。 - Martin
1
隧道并不是无用的,它只是用于不同于您尝试的任务。例如,它可以通过捕获按键并在到达 TextBox 之前取消事件来禁止在 TextBox 中输入某些字符。 - Adi Lester

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接