WPF FrameworkElement未接收鼠标输入

时间:2010-07-16 21:52:10

标签: wpf mouseevent frameworkelement routedevent

尝试让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);
    }
}

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>

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

2 个答案:

答案 0 :(得分:21)

仅当您的元素响应命中测试时,才会调用

OnMouseDown。见Hit Testing in the Visual Layer。默认实现将针对OnRender中绘制的图形进行命中测试。创建具有Panel背景的Transparent是有效的,因为Panel在其整个区域上绘制了一个矩形,并且该矩形将捕获命中测试。您可以通过覆盖OnRender来绘制透明矩形来获得相同的效果:

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

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

protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
{
    return new PointHitTestResult(this, hitTestParameters.HitPoint);
}

答案 1 :(得分:1)

我能够重现你描述的场景。我做了一些游戏,直到我将MyFrameworkElement的基类从FrameworkElement更改为更具体的内容,例如UserControl,事件开始像他们应该开始一样。我不是100%确定为什么会这样,但我建议使用一个适合您需求的FrameworkElement派生类(如Panel,如上例所示,或者Button)。

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