WPF中的VisualTreeHelper.HitTest问题

时间:2010-08-05 05:11:14

标签: wpf hittest visualtreehelper

我正试图在Canvas上测试一堆UserControl。我不希望HitTest()在整个可视树中走路,所以我使用FilterCallback来确保我只测试UserControl。

我的问题是UserControl永远不会命中,它应该,但事实并非如此。如果我使用FilterCallback,我会返回它什么都没有。如果我让HitTest运行可视树,它会跳过UserControl。

以下是一些代码:

<Canvas x:Name="Container">
<UserControl>
   <Grid>
      <Rectangle />
   </Grid>
</UserControl>
<UserControl>
   <Grid>
      <Rectangle />
   </Grid>
</UserControl>
</Canvas>

...
VisualTreeHelper.HitTest(Container, OnFilter, OnResult, myPoint);
...

private void OnResult(DependencyObject o)
{
   //I'll get the Rectangle here, but never the userControl  
}

private void OnFilter(DependencyObject o)
{
   //I will get the UserControl here, but even when I do nothing more than continue, it will not trigger a visualHit.  But the child rectangle will.
}

2 个答案:

答案 0 :(得分:11)

我知道回答这个问题已经很晚了但是接下来是:另一种方法是覆盖UserControl上的HitTestCore并为其提供预期的默认行为:

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

(当然你可以复杂化并测试实际的孩子或他们的边界框的组合,但对我来说,用户控件的边界框已经足够了;另外,如果你想针对几何体进行测试你也需要覆盖那个第二个重载。)

这使其按预期工作,在过滤器中使用HitTestFilterBehavior.ContinueSkipChildren时过滤掉子项。

答案 1 :(得分:2)

我有同样的问题,HitTest找不到用户控件。显然这是设计的(http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/005dad03-c8eb-405f-9567-50653a0e612c)。

我通过处理用户控件中某些元素的命中,然后使用VisualTreeHelper.GetParent方法查找父用户控件来解决这个问题。我还不熟悉WPF,所以我不确定使用FrameworkElement.Parent属性是否更好。

但是,这是我通过命中测试找到一些内容元素后找到用户控件(或某些必需类型的可视父级)的方法:

public static T GetVisualParent<T>(this DependencyObject element) where T : DependencyObject
{
    while (element != null && !(element is T))
        element = VisualTreeHelper.GetParent(element);

    return (T)element;
}