Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF UIElement.IsHitTestVisible=false; still returning hits?

Tags:

c#

wpf

I'm deriving a control from FrameworkElement to use as a container for a VisualCollection, as I'm doing a lot of custom rendering using DrawingVisuals (creating a game map).

I've got a couple different instances of my container layered on top of each other, and I only want hit testing to affect the layer currently visible, so I tried doing the obvious, and set .IsHitTestVisible=false, which according to MSDN should prevent any child elements being returned as hit results.

However, I am still getting hits returned on the containers that are set .IsHitTestVisible=false. I've tried everything else I can think of, Collapsed, Hidden, Disabled, 0 Opacity, nothing seems to take it out of the hit testing.

like image 341
Kal_Torak Avatar asked Jan 27 '11 06:01

Kal_Torak


1 Answers

I think it's a bug. I used Reflector to understand why the HitTest method returns invisible items and I have found that there is no check for visibility.

My solution is to use overload HitTest with filter:

public static HitTestFilterBehavior HitTestFilterInvisible(DependencyObject potentialHitTestTarget)
{
    bool isVisible = false;
    bool isHitTestVisible = false;

    var uiElement = potentialHitTestTarget as UIElement;
    if (uiElement != null)
    {
        isVisible = uiElement.IsVisible;
        if (isVisible)
        {
            isHitTestVisible = uiElement.IsHitTestVisible;
        }
    }
    else
    {
        UIElement3D uiElement3D = potentialHitTestTarget as UIElement3D;
        if (uiElement3D != null)
        {
            isVisible = uiElement3D.IsVisible;
            if (isVisible)
            {
                isHitTestVisible = uiElement3D.IsHitTestVisible;
            }
        }
    }

    if (isVisible)
    {
        return isHitTestVisible ? HitTestFilterBehavior.Continue : HitTestFilterBehavior.ContinueSkipSelf;
    }

    return HitTestFilterBehavior.ContinueSkipSelfAndChildren;
}
...
// usage:

    VisualTreeHelper.HitTest(
        myHitTestReference,
        HitTestFilterInvisible,
        hitTestResult =>
        {
            // code to handle element which is visible to the user and enabled for hit testing.
        },
        new PointHitTestParameters(myHitTestPoint));

I hope it will help you

like image 181
Marat Khasanov Avatar answered Oct 05 '22 23:10

Marat Khasanov