This blog post describes a simple helper class that can be used to supress scrolling and pinch zoom of the Windows Phone 7 WebBrowser control.
Developers of Windows Phone 7 application have the full power of IE9 at their disposal in the shape of the WebBrowser
control. This control allows you to render both local and remote HTML and JavaScript content within your Silverlight applications. You will find this control used to great effect in RSS readers and Twitter applications such as Rowi, where websites are viewed from within the application rather than by launching the full-blown IE. The WebBrowser control is also used as the host / container for HTML5 based applications, such as Property Finder, the PhoneGap-based application I developed recently.
One problem them people frequently hit against with the WebBrowser
control is managing the manipulation events. For example, if you place a WebBrowser control within a Pivot control, how can you pass the horizontal swipe gesture form the WebBrowser to the Pivot?
With HTML5 applications you have a certain amount of control over the browser's pan and zoom behaviour via the viewport metadata HTML element:
Adding the above meta-tag to a HTML page will prohibit the user from zooming via the pinch gesture. However, it does this in a rather clumsy way - the user can still pinch the page, but when they release, it snaps back to its original scale.
Whilst this might be OK in some contexts, for a HTML5 application where intention is to replicate the feel of a native application as closely as possible, this is just not good enough. Another little browser quirk that has a similar effect is the scroll behaviour. Even if a page fits entirely within the area occupied by the WebBrowser control, they can still scroll the content. Again, it simply snaps back to its original location.
The Solution
I initially thought that there would be no way for me to control the behaviour of the WebBrowser
control, it is after-all a very thin .NET wrapper around a native control. However, I stumbled across some StackOveflow answers from quetzalcoatl who had done some digging around in the .NET wrapper and had identified an interesting control called the PanZoomContainer
.
If you inspect the visual tree of the WebBrowser
control you will find that it is assembled as follows:
\-WebBrowser \-Border \-Border \-PanZoomContainer \-Grid \-Border (*) \-ContentPresenter \-TileHost
(visual tree dump generated via the oh-so-useful Linq to VisualTree utility!)
The visual tree is quite simple, composed of a few grids and borders. The significant parts are the TileHost
, which is the native IE9 component, and the PanZoomContainer
. The TileHost does not handle the mouse manipulation events, these are instead handled by the PanZoomContainer
, where they are then translated into gestures (i.e. pinch-zoom) with the result fed back to the TileHost
.
What this means is that we can intercept the manipulation events as they bubble up to the PanZoomContainer
, cancelling them before they are turned into gestures.
The utility class which I have written handles the events on the Border
indicated above. When events are received various conditions are checked to identify pan or scroll interactions, with the events being cancelled accordingly.
The complete class is given below:
Within Property Finder, my HTML5 application, as the user navigates from one page to the next, the JavaScript code notifies the Silverlight container whether the current page should have scrolling disabled, setting the ScrollDisabled
property of the above helper class accordingly.
I hope other people find this simple utility class useful. To use it, just cut and paste the code given above. Note, it uses Linq to VisualTree to navigate the WebBrowser
visual tree, so you will need to go and grab that also.
Regards, Colin E.