Problem with VisualTreeHelper.HitTest in WPF

I am trying to try a bunch of UserControls on canvas. I do not want HitTest () to go all the way through the visual tree, so I use FilterCallback to make sure that I only checked UserControl.

My problem is that UserControl never hits, but it is not. If I use FilterCallback, I return that it didn't hit anything. If I let HitTest go through the visual tree, it skips the UserControl.

Here is the 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. } 
+4
source share
2 answers

I had the same issue as HitTest without finding user control. Apparently this is by design ( http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/005dad03-c8eb-405f-9567-50653a0e612c ).

I worked on this by handling the hit of an element inside a user control, and then finding the parent control of the user using the VisualTreeHelper.GetParent method. I'm not very familiar with WPF yet, so I'm not sure it would be better to use the FrameworkElement.Parent property.

However, here is my method of searching for a user control (or any visual parent of any desired type) after the first search for some of its content elements using a test test:

 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
source

I know it’s rather late to answer this, but here we are talking about: another approach is to override HitTestCore in UserControl and provide it with the default behavior that you would expect 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 the situation and try out actual children or a combination of your bounding boxes, but for me the bounding box of the user control was good enough, and if you want to test against geometry you also need to override this second overload.)

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

+11
source

All Articles