1

I'm trying to eliminate TouchDevices in a WPF for Surface so I can ignore non-finger touches because blobs seem to trigger events I don't want.
At first I had something simple like this

private void SurfaceWindow1_PreviewTouchDown(object sender, TouchEventArgs e)
    {
        if (!e.TouchDevice.GetIsFingerRecognized() && InteractiveSurface.PrimarySurfaceDevice.IsFingerRecognitionSupported == true)
        {
            e.Handled = true;
        }

    }

Which works well to stop touch interactions with things like inside ScatterViewItems and manipulations. however there must be something else that happens before PreviewTouchDown because I can use a blob to activate an SVI and bring it to the top although no other manipulations occur. I'm guessin TouchEnter on the SVI still shows up and brings it forward but handling TouchEnter on all the elements gives me the same thing so there's still something else going on.

I looked into Touch.FrameReported but I can't release the proper TouchCaptures before the SVIs hear about it

    private void myTouchFrameHandler(object sender, TouchFrameEventArgs e)
    {
        foreach (TouchPoint _tp in e.GetTouchPoints(this)) {
            if (!_tp.TouchDevice.GetIsFingerRecognized())
            {
                this.ReleaseAllTouchCaptures();    
            }
        }
    }

Any ideas?
Thanks

aleatoric
  • 68
  • 9

3 Answers3

2

I stumbled upon the same problem and implemented an attached behavior for ScatterViewItems. This behavior disables the automatic IsTopmostOnActivation behavior and listens to PreviewTouchDown events to decide if an item is to be brought to top based on a test condition. It features an easy to use activation method

CustomTopmostBehavior.Activate();

which adds an application-wide style enabling the behavior for all ScatterViewItems.

The behavior can be customized by setting its TestCondition property which is by default:

CustomTopmostBehavior.TestCondition = (t) =>
{
    return t.GetIsFingerRecognized();
};
Dominik
  • 90
  • 2
  • 8
  • wow this solution is way more robust! These attached properties are pretty cool, I'll have to look into that, and I didn't know there was a Relative ZIndex stack. This makes SUR40 a solid touchscreen. Thanks a million! – aleatoric Mar 26 '12 at 14:06
  • Yea, I quite got to appreciate attached properties and behaviors :). They make for nice and flexible solutions. – Dominik Apr 03 '12 at 11:02
1

Ok here's my dirty workaround to stop Touches from advancing when they're not recognized as fingers, and stopping SVIs from rising to the top when hovered over.

    this.PreviewTouchDown += new EventHandler<System.Windows.Input.TouchEventArgs>(SurfaceWindow1_PreviewTouchDown);    
    SVI.TouchEnter += new EventHandler<TouchEventArgs>(SVI_TouchEnter);
    SVI.TouchLeave +=new EventHandler<TouchEventArgs>(SVI_TouchLeave);

    void SurfaceWindow1_PreviewTouchDown(object sender, System.Windows.Input.TouchEventArgs e)
    {

        if (!e.TouchDevice.GetIsFingerRecognized() && Microsoft.Surface.Presentation.Input.InteractiveSurface.PrimarySurfaceDevice.IsFingerRecognitionSupported) { e.Handled = true; }
        else
        {
           //normal stuff
        }



    }
    private void SVI_TouchEnter(object sender, TouchEventArgs e)
    {
        ScatterViewItem svi = sender as ScatterViewItem;

        if (!e.TouchDevice.GetIsFingerRecognized() && Microsoft.Surface.Presentation.Input.InteractiveSurface.PrimarySurfaceDevice.IsFingerRecognitionSupported == true)
        {
            svi.IsTopmostOnActivation = false;
            e.Handled = true;
        }
        else
        {
            foreach(ScatterViewItem svi in mainScatterView.Items.SourceCollection){
                svi.IsTopmostOnActivation = false;
            }

            SVI.IsTopmostOnActivation = true;
        }

    }
    private void SVI_TouchLeave(object sender, TouchEventArgs e)
    {
            ScatterViewItem svi = sender as ScatterViewItem;
            svi.IsTopmostOnActivation = true;
    }

I feel gross just coming up with such an unclever method. But since there's no tunneling TouchEnter, you would have to check all the visual tree objects that get a TouchEnter, which would even worse. Plus I just couldn't figure out how to use the protected method TouchDevice.Deactivate() anyway. But since the SVIs capture the touchDevice anyway and get restacked the only way I found to keep them in place is with the TopmostOnActivation Property, then catch the PreviewTouchDown on the Window and throw out non-fingers.

There's got to be a better way to get into the touch hierarchy, right?

aleatoric
  • 68
  • 9
0

OK so I've dug deeper into the touch hierarchy. First of all TouchEnter happens before all the TouchDowns occur, but there's no tunneling event for that. TouchFrameHandler occurs after all the events are done, so throw that out.

Then I realized Releasing Captures on UIElements doesn't really make a difference for my problem because the Touch is already Captured. So I need to eliminate the TouchDevice in TouchEnter on every element. There is a Deactivate method in TouchDevice but it's protected. If I can figure out how to Deactivate a TouchDevice I think that should do the trick. Does that sound reasonable? If so I have to figure out how to override a protected method.

aleatoric
  • 68
  • 9