PreviewMouseDown未按预期进行隧道传输

Zma*_*ter 4 wpf mouse routed-events

我的应用程序上有以下树:

MainWindow (Window)
> LayoutRoot (Grid)
  > (MyCustomControl)
    > Item1 (Grid)
      > Button (Button1)
Run Code Online (Sandbox Code Playgroud)

MyCustomControl派生自ItemsControl并在StackPanel上显示其项目.

MyCustomControl需要知道什么时候单击鼠标本身,所以我已经覆盖OnPreviewMouseDown方法,并希望得到任何鼠标按下我的控件内的通知.

会发生什么:如果我在Button1中单击,则PreviewMouseDown事件沿树传播,并按预期执行OnPreviewMouseDown.但是,如果我点击Item1,则PreviewMouseDown事件会在MainWindow之后停止,甚至不会达到LayoutRoot.

以下是我使用Snoop获得的路由事件详细信息:

单击Button1:

(Window)
> (Border)
  > (AdornerDecorator)
    > (ContentPresenter)
      > LayoutRoot (Grid)
        > (MyCustomControl)
          > (Border)
            > (StackPanel)
              > Item1 (Grid)
                > Button1 (Button)
                  > Chrome (ButtonChrome)
Run Code Online (Sandbox Code Playgroud)

单击Item1:

(Window)
> (Border)
Run Code Online (Sandbox Code Playgroud)

该事件从未报告为已处理,因此据我所知,它应该继续进行隧道传输.

我在这里失踪了什么?

Cod*_*ked 6

您需要确保自定义控件是可以测试的.如果您有一个ControlTemplate,如:

<ControlTemplate>
    <ItemsPresenter />
</ControlTemplate>
Run Code Online (Sandbox Code Playgroud)

那么你的自定义控件本身就不会受到测试.即使你有一个像ControlTemplate:

<ControlTemplate>
    <Border Background="{TemplateBinding Background}" ...>
        <ItemsPresenter />
    </Border>
</ControlTemplate>
Run Code Online (Sandbox Code Playgroud)

然后,如果Background为null,那么您的控件本身就不会是可测试的.如果您只是将Background属性设置为Transparent,那么它将是hit-testable.

经验法则是,如果您的控件或其中一个后代未在给定位置(即像素)渲染某些内容,即使它是透明的,则鼠标也不会为其注册事件.