I came across an interesting problem at work recently when I had a canvas inside a ScrollViewer. I was developing a windows 8 application and I had a control that was essentially a canvas that handled drawing, and this was situated inside of a ScrollViewer. The control worked fine with the mouse, allowing me to draw on it, but when it came to touch, the control no longer worked, as all touch events were transferred to the ScrollViewer and instead my page scrolled.
I thought I was doing everything correctly. The events were being set as handled, so they shouldn’t propagate to the ScrollViewer. However after much research I discovered it was still possible for controls to respond to handled events, and this must have been what the scrollviewer was doing.
After trying many different options, I eventually stumbled upon the solution. There is a property on UIElements called ManipulationMode. Setting the value of ManipulationMode to “All” on the canvas prevents the scrollviewer from responding to the touch events on the canvas. I believe what this does is it sets the control to handle all Manipulations that occur on it.
The default value for ManipulationMode is System. The following quote from MSDN helps explain some of this:
In Windows Phone OS 7.1, the ManipulationMode property enables you to specify how most of the property updates and events associated with scrolling a ScrollViewer are handled. You can specify that the system will handle the manipulations or that you will handle the manipulations at the control level. In most cases, to ensure smooth scrolling, you should let the system handle the manipulations, which is the default behavior.
This refers to silverlight in Windows Phone OS 7.1, however I believe much of this must be the same in Winrt. The above quote explicitly relates to the Manipulation mode on the ScrollViewer. You can see from the explanation, ScrollViewer actually passes the scroll events through to the System, to allow the System to handle scrolling. Therefore, by setting our canvas to handle all Manipulations, the touch events for scrolling never get passed through to our ScrollViewer, hence it can’t pass them through to the System.
There may be a better way to do this, and I would love to hear about it in the comments, but I thought I would share my experience, as this took quite a bit of figuring out, and I hope it can help someone else out!