2

I am using the VisualTreeHelper to perform a HitTest on a button that looks like this...

<Button Width="100"
    Height="100"
    HorizontalAlignment="Center"
    VerticalAlignment="Center"
    Background="Purple">
    Hello world
</Button>

However when I perform the actual HitTest as such:

HitTestResult result = VisualTreeHelper.HitTest(_ContentHolder, new Point(xTransform, yTransform));
if (result != null)
{               
}

The returned object looks like this VisualHit = {System.Windows.Controls.Border} which doesn't quite make sense to me.

Could anyone please provide any guidance as to what I might be doing wrong, how I would return the actual Button object (such that I can trigger any event handlers) and why I may be experiencing such behaviour?

Maxim Gershkovich
  • 45,951
  • 44
  • 147
  • 243
  • Question: Wouldn't it be easier to just use an **Event Handler** on the `Button`? – Mike Eason Jun 12 '15 at 14:39
  • Absolutely, but I am trying to emulate mouse functionality without commandeering the actual mouse, so as far as I understand this is my only option. – Maxim Gershkovich Jun 12 '15 at 14:42
  • What kind of hell are you living in? – Mike Eason Jun 12 '15 at 14:43
  • If you want to specific Elements like button you can use HitTestFilterCallback to filter the elements. Refer https://msdn.microsoft.com/en-us/library/ms752097(v=vs.110).aspx – Ayyappan Subramanian Jun 12 '15 at 14:44
  • @MikeEason hahahahahah. I can't even begin to describe it... I am trying to emulate something called the KinectRegion if you are interested in finding out more check out this link https://msdn.microsoft.com/en-us/library/microsoft.kinect.xaml.controls.kinectregion.aspx – Maxim Gershkovich Jun 12 '15 at 14:46

1 Answers1

1

If you look at the control template for the Button here you can see that it is composed almost entirely of a Border control. Since the Border is what actually took the hit, that is what is being returned. You should use a common helper function to walk up the visual tree to find the actual button.

public static T FindParent<T>(DependencyObject child) where T : DependencyObject
{
    //get parent item
    DependencyObject parentObject = VisualTreeHelper.GetParent(child);

    //we've reached the end of the tree
    if (parentObject == null) return null;

    //check if the parent matches the type we're looking for
    T parent = parentObject as T;
    if (parent != null)
        return parent;
    else
        return FindParent<T>(parentObject);
}

Call this function, passing in the result of the hit test and specifying Button as the type should return the parent button that was hit.

Now... With all that being said, you might be going about what you are trying to do the wrong way. Without more details about what you are doing and, more importantly why, it could be hard to guide you.

Bradley Uffner
  • 16,641
  • 3
  • 39
  • 76
  • Absolutely fantastic, worked exactly as required and thank you for the *why*. I suspected that the Button might actually be a border but wasn't sure how to verify. As stated above I am trying to emulate a Mouse without actually commandeering the mouse to create my own implementation of the KinectRegion (as described in this link https://msdn.microsoft.com/en-us/library/microsoft.kinect.xaml.controls.kinectregion.aspx) - Sincerely appreciate your help... – Maxim Gershkovich Jun 12 '15 at 14:50
  • I don't think I've ever written anything in WPF without calling this function at least once. Why it isn't built in is beyond me. – Bradley Uffner Jun 12 '15 at 14:52
  • Yep, I'm only a few months in working with WPF having moved from Windows Forms and it is rather challenging to get your head around. Unfortunately much of the structure and functionality of WPF isn't always implicitly apparent. Thanks again for your help, will mark as answer as soon as it allows me... – Maxim Gershkovich Jun 12 '15 at 14:54