Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem with VisualTreeHelper.HitTest in WPF

I'm trying to hit-test a bunch of UserControls on a Canvas. I don't want the HitTest() to walk the whole way through the visual tree, so I'm using the FilterCallback to make sure I only hit-test the UserControl.

My problem is that the UserControl never hits, it should, but it doesn't. If I use the FilterCallback, I return that it hit nothing. If I let the HitTest run through the visual tree, it skips the UserControl.

Here's some code:

<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.
}
like image 289
Chris Nicol Avatar asked Dec 09 '22 14:12

Chris Nicol


1 Answers

I know it's pretty damn late to answer this but here goes: a different approach is to override HitTestCore on the UserControl and provide it with the default behavior that would be expected from it:

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

(of course you could complicate things and hit-test the actual children or the combination of their bounding boxes, but for me the bounding box of the user control was good enough; also, if you want to hit-test against geometry you need to override that second overload as well.)

This makes it work as expected, filtering out the children when using HitTestFilterBehavior.ContinueSkipChildren in the filter.

like image 135
Alex Paven Avatar answered Jan 03 '23 07:01

Alex Paven