WPF FrameworkElement未接收鼠标输入

lav*_*ava 10 wpf routedevent mouseevent frameworkelement

试图让OnMouse事件出现在孩子身上FrameworkElement.父元素是Panel(并且Background属性不是Null).

class MyFrameworkElement : FrameworkElement
{
    protected override void OnMouseDown(MouseButtonEventArgs e)
    {
        // Trying to get here!
        base.OnMouseDown(e);
    }
}

public class MyPanel : Panel
{
    protected override void OnMouseDown(MouseButtonEventArgs e)
    {
        // This is OK
        base.OnMouseDown(e);
    }
}
Run Code Online (Sandbox Code Playgroud)

OnMouse永远不会被调用,事件总是未被处理,Snoop告诉我,路由事件似乎只能到达Panel元素.

<Window 
  x:Class="WpfApplication5.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:l="clr-namespace:WpfApplication5"
  Title="Window1" Height="300" Width="300">
  <Border x:Name="myBorder" Background="Red">
    <l:MyPanel x:Name="myPanel" Background="Transparent">
      <l:MyFrameworkElement x:Name="myFE"/>
    </l:MyPanel>
  </Border>
</Window>
Run Code Online (Sandbox Code Playgroud)

文档说FrameworkElement处理输入,但为什么不在这种情况下?

Qua*_*ter 23

OnMouseDown只有当你的元素响应命中测试时才会被调用.请参阅可视层中的命中测试.默认实现将针对绘制的图形进行命中测试OnRender.创建Panel具有Transparent背景的工作因为Panel在其整个区域上绘制一个矩形,并且该矩形将捕获命中测试.您可以通过覆盖OnRender绘制透明矩形来获得相同的效果:

protected override void OnRender(DrawingContext drawingContext)
{
    drawingContext.DrawRectangle(Brushes.Transparent, null, 
        new Rect(0, 0, RenderSize.Width, RenderSize.Height));
}
Run Code Online (Sandbox Code Playgroud)

您也可以覆盖HitTestCore以便将所有点击计为点击数:

protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
{
    return new PointHitTestResult(this, hitTestParameters.HitPoint);
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*ter 1

我能够重现您所描述的场景。我做了一些尝试,直到我将MyFrameworkElementfrom的基类更改FrameworkElement为更具体的东西,就像UserControl事件开始按其应有的方式触发一样。我不是 100% 确定为什么会这样,但我建议使用从中派生的类之一来FrameworkElement满足您的需求(例如Panel,如您在上面的示例中所做的那样,或Button)。

我很想知道上面的示例产生这些结果的确切原因......