代码之家  ›  专栏  ›  技术社区  ›  Chris Nicol

WPF中VisualTreeHelper.HitTest存在问题

  •  4
  • Chris Nicol  · 技术社区  · 16 年前

    我正在测试画布上的一堆用户控件。我不希望hitTest()在可视化树中穿行,所以我使用filterCallback来确保只测试用户控件。

    我的问题是,用户控件从未命中,它应该命中,但它没有命中。如果使用filtercallback,我返回它未命中。如果让HitTest在可视化树中运行,它将跳过用户控件。

    下面是一些代码:

    <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 回复  |  直到 15 年前
        1
  •  2
  •   Riikka Heikniemi    16 年前

    我也有同样的问题,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;
    }
    
        2
  •  11
  •   Alex Paven    15 年前

    我知道现在回答这个问题已经非常晚了,但是这里有一个不同的方法:重写用户控件上的Hitestcore,并为它提供预期的默认行为:

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

    (当然,您可能会使事情复杂化,并点击测试实际的子对象或其边界框的组合,但对我来说,用户控件的边界框已经足够好了;此外,如果您想点击针对几何体的测试,还需要覆盖第二个重载。)

    这使它按预期工作,在使用时筛选出子级 HitTestFilterBehavior.ContinueSkipChildren 在过滤器中。

    推荐文章