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.
Colin Eberhardt is a Scott Logic technical Evangelist and a Technical Architect for Visiblox, suppliers of high-performance WPF and Silverlight charts.
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:
<meta name="viewport" content="user-scalable=no" /> |
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:
using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using LinqToVisualTree; using Microsoft.Phone.Controls; /// <summary> /// Suppresses pinch zoom and optionally scrolling of the WebBrowser control /// </summary> public class WebBrowserHelper { private WebBrowser _browser; /// <summary> /// Gets or sets whether to suppress the scrolling of /// the WebBrowser control; /// </summary> public bool ScrollDisabled { get; set; } public WebBrowserHelper(WebBrowser browser) { _browser = browser; browser.Loaded += new RoutedEventHandler(browser_Loaded); } private void browser_Loaded(object sender, RoutedEventArgs e) { var border = _browser.Descendants<Border>().Last() as Border; border.ManipulationDelta += Border_ManipulationDelta; border.ManipulationCompleted += Border_ManipulationCompleted; } private void Border_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e) { // suppress zoom if (e.FinalVelocities.ExpansionVelocity.X != 0.0 || e.FinalVelocities.ExpansionVelocity.Y != 0.0) e.Handled = true; } private void Border_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) { // suppress zoom if (e.DeltaManipulation.Scale.X != 0.0 || e.DeltaManipulation.Scale.Y != 0.0) e.Handled = true; // optionally suppress scrolling if (ScrollDisabled) { if (e.DeltaManipulation.Translation.X != 0.0 || e.DeltaManipulation.Translation.Y != 0.0) e.Handled = true; } } } |
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.
Tags: HTML5, PhoneGap, WebBrowser, Windows Phone 7


email: ceberhardt@scottlogic.co.uk
on Google+



Has anyone got this working in WP8 app?. This solution does not seem to be working on WP8 app. If anyone has got it working please do post the solution.
I tried disabling the scrolling only not pinch/zoom. So I have no idea if they work in WP8 apps. suppressing the scroll of WebBrowser seems to be not working on WP8
I can second that. Horizontal scrolling seems to be suppressed, but vertical scrolling is still there.
Hi
Do you know of any way to turn of the bounce effect in a webbrowser control in Windows Phone? When i scroll down, and then scroll upp the content bounces up and down when reaching the top. Like asked for in http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/ed3cd7f7-1163-45e7-ba5c-27764e496a32/
Sorry Erik – no, I don’t know how to do that,
Try adjusting the height of webbrowser
Thanks for the article!
2 questions:
Any idea how to suppress zooming in a XAML WebView Control in WinRT (Windows 8)?
Is there a version of the LinqToVisualTree API for WinRT?
cheers,
Thomas
Hi,
I have not tried using this technique for Windows 8 – sorry!
Regarding LinqToVisualTree, the Silverlight / WPF version should work just fine in WinRT, you just need to change the namespaces at the top of the file.
Colin E.
In WP8, the Visual Tree seems to be updated after the Loaded event occured. Using the LayoutUpdated instead event worked for me.
Hi,
I have one image displayed on webbrowser on simple phone application page and i dont want it to be scroll up or down .I tried above things to suppress scrolling but its still not working in my case.can anyone help me please???
I have a panorama conrol with sebbrowser as an item.since i want to move panorama item by swiping web browser i used your code with little moidification.In windows phone 7.1 is working.But in Windows Phone 8 app is not working for me
here is my code
private void Browser_Loaded(object sender, RoutedEventArgs e)
{
border = AssociatedObject.Descendants().Last() as Border;
mainBorder = AssociatedObject.Ancestors().Last() as Border;
border.ManipulationDelta += Border_ManipulationDelta;
border.ManipulationCompleted += Border_ManipulationCompleted;
mainBorder.ManipulationCompleted += mainBorder_ManipulationCompleted;
}
void mainBorder_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
{
AssociatedObject.IsEnabled = true;
}
private void Border_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
{
// suppress zoom
if (e.FinalVelocities != null)
{
if (e.FinalVelocities.ExpansionVelocity.X != 0.0 ||
e.FinalVelocities.ExpansionVelocity.Y != 0.0)
e.Handled = true;
}
}
private void Border_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
// suppress zoom
if (e.DeltaManipulation.Scale.X != 0.0 ||
e.DeltaManipulation.Scale.Y != 0.0)
e.Handled = true;
// optionally suppress scrolling
if (ScrollDisabled)
{
if (e.DeltaManipulation.Translation.X != 0.0 ||
e.DeltaManipulation.Translation.Y != 0.0)
e.Handled = true;
}
if (Math.Abs(e.CumulativeManipulation.Translation.X) > 10.0 && Math.Abs(e.CumulativeManipulation.Translation.Y) < 20.0)
{
var items = AssociatedObject.Ancestors();
if (items != null && items.Count() > 0)
{
(items.First() as PanoramaItem).Focus();
}
else
{
items = AssociatedObject.Ancestors();
if (items != null && items.Count() > 0)
{
(items.First() as PivotItem).Focus();
}
}
if (items != null && items.Count() > 0)
{
AssociatedObject.IsEnabled = false;
}
}
}
[...] want your user to be able to use touch events in a very rich way. In this scenario, you can either turn off scrolling the hard way (also known as the Windows Phone 7 compatible way) or the easy way, which is to go into your phone.css and [...]
Hi,Colin. Thanks for your work. I just want to knwn if there ia any way to “Suppressing Zoom and Scroll interactions in the Windows 8 Metro style applicaiton WebView Control”
Thanks.
Hi Ellic – no, I have not tried this on Windows 8.
Hi Colin,
thanks for the solution…..i have been using this snippet of code to stop scroll in my app done using phonegap … i am facing some problem after using it when
ever on my app i try to swipe i get this error nullreferenceexception unhandled this appears not frequently but when appears app quits pls help
Thanks for this excellent post. I converted the code to vb for use in my project, and posted the adapted code.
http://ericsgems.wordpress.com/2012/09/01/daily-gem-vb-silverlight-wp7-disable-pinch-or-scroll-in-ie9-webbrowser-control/
Thanks for porting
[...] http://www.scottlogic.co.uk/blog/colin/2011/11/suppressing-zoom-and-scroll-interactions-in-the-windo… [...]
Hi,
I need to disable the scrolling on my web browser control but still want the user to interact with it at the same time.
Your code should be useful but the following line is giving me error:
var border = _browser.Descendants().Last() as Border;
The Web Browser doesn’t seem to have a ‘Descendents’ member. Can you tell me how did you get it? I am using SDK 7.1
[...] decided to spend a little bit more time in Bing, and on far from the first page managed to find the solution. Some guy spend some considerable time to find what exactly has to be changed in the hierarchy of [...]
Hi,thanks for this. It works very well.
I have another question which is very similar to this.
I want disable double tap to zoom. when I double click, the browser always zoom in and then zoom out quickly. How can I suppress double tap to zoom?
Thanks.
Hi,
You simply need to suppress the double-tap event. Try adding the following code
private void browser_Loaded(object sender, RoutedEventArgs e) { var border = _browser.Descendants().Last() as Border;
border.ManipulationDelta += Border_ManipulationDelta;
border.ManipulationCompleted += Border_ManipulationCompleted;
border.DoubleTap += Border_DoubleTap;
}
private void Border_DoubleTap(object sender, GestureEventArgs e)
{
// suppress double-tap zoom
e.Handled = true;
}
You can download a working example from this blog post.
Thanks very much. You really do a great favor to me.
Hi!
I’m working on a PhoneGap (1.7) app and have tried this.
1. It works great, thank you for this work!
2. It works to good… I can not scroll my inner containers anymore =)
The problem is, that I’m having some containers in my app where the user has to be able to scroll. Your code just blocks the input on a to hight level =/
I have not found a way to distinguish where the user “clicked” to scoll…
My only idea was to use ur Manager (from an other post) set “scrolling” to false and enable it when the user “clicks” the scrollable container… should be possible to implement but I want to keep the HTML/JS code clean from device specific solutions =/
Do you have any ideas about this problem?
Greetings
No, I’ve not tried this with nested scrolling containers, and yes, I can see why that would break. Sorry, no solutions for this one!
Instead of e.Handled then, shouldn’t the click be routed/bubbled up to the ScrollViewer wrapping the WebBrowser control? Been a while since I did stuff like that…
[...] creation of HTML5 project and enabling communications between your WP7 application and javascript.http://www.scottlogic.co.uk/blog/colin/2011/11/suppressing-zoom-and-scroll-interactions-in-the-windo… - some useful information about the visual tree structure of WebBrowser component in WP7.Ok, so [...]
This doesn’t seem to be working for me. I get the Border using the LinqToVisualTree helper, but when I inspect it, it seems to be the second border (not the third one) so it doesn’t get the manipulation events. I tried manually digging down into the visual tree, but I can’t get past the PanZoomContainer. When I try to get the visual child of the PanZoomContainer, I get nothing.
Any ideas what I’m doing wrong?
Hi,
I have used this and its working fine for me. But now next question is, I want to disable the selection color on web browser(setting the color to Transparent), do you have any idea how can I achieve that?
Thanks
/
Apu
Hi Apu,
No, there is no solution to this problem. See the question I posted on Stack Overflow.
That is an amazing perception. I have a webBrowser which has to scroll vertically and not horizontally so I can use your solution with a little modification.
[...] just want to turn off scrolling/zooming of the webpage. Colin Eberhardt did the initial research (blog post here) and discovered how the WebBrowser control’s view stack is defined, and discovered how to prevent [...]
[...] the way I have solved problems such as back-button support, tombstoning and suppressing browser pan and zoom. var addthisButtonFacebook = document.getElementById('addthisButtonFacebook'); var [...]
If you flick up the webbrowser control instead of drag, it still can scroll. Any thought?
Yes that’s true it doesn’t work for flick :/
We are facing an issue in locking pinch zoom and scroll lock in
browser web page. We have created an application using phonegap.In that web page, we
want to lock the pinch zoom and scroll lock(Lock for Web View) in Windows Phone 7.5 mango
Can you show an example how to use this class? I’m just HTML5 developer, and all C# things is new to me. But I need this fix for PhoneGap…
Thanks in advance
Hi Alius, I am just finishing of a blog post that will do just that. Keep a look out on my RSS feed.
Hi Colin E.,
This solution works with a PhoneGap project like your Property Finder? And works in the WP7 Emulator? Because I start a Hello World PhoneGap project, added the WebBrowserHelper.cs and VisualTreeAdapter.cs classes but nothing changes… the zoom and scroll effects persist.
Where I find a complete example or how did you configured your files and MainPage.xaml MainPage.xaml.cs?
Thank you for your patience…
Hi, I am just finishing off a new blog post that provides a complete example of how to use this code. Keep an eye on my RSS feed.
I am HTML5 mobile games and apps developer. i use the above code but i gave some error
at the line in var border = _browser.Descendants().Last() as Border; Microsoft.Phone.Controls.WebBrowser does not contain a definition for descendants and the best extension methos overload and Instance argument cannot convert from Microsoft.Phone.Controls.WebBrowser toSystem.Collections.Generic.IEnumerable’
I added the reference in System.Xml.Linq. how to solve the error or how to disable the page scrolling and zooming controls in web browser in WP7
Hi,
As stated in the article, it has a dependency to Linq-To-VisualTree (http://www.scottlogic.co.uk/blog/colin/2010/03/linq-to-visual-tree/), simply add Linq-To-VisualTree to your project and add
using LinqToVisualTree;
I have updated the code-snippet above to make it more obvious!
Colin E.
We can not convert into visual studio 2010. what procedure to convert visual studio 2010
Hi,
I am trying with your example but ” _browser.Descendants().Last() as Border;” is showing error. Its showing “‘Microsoft.Phone.Controls.WebBrowser’ does not contain a definition for ‘Descendants’ ”
I am using Windows Phone SDK 7.1. Do you have any idea why its not working?
Thanks
/
Apu
Hi,
As stated in the article, it has a dependency to Linq-To-VisualTree (http://www.scottlogic.co.uk/blog/colin/2010/03/linq-to-visual-tree/), simply add Linq-To-VisualTree to your project and add
using LinqToVisualTree;
I have updated the code-snippet above to make it more obvious!
Colin E.
Thanks Colin. It works now.
I tried looking through your code for Property Finder to see how you’re implementing WebBrowserHelper, but I can’t find any mention of it. How are you implementing it? I got the code from this page: http://www.scottlogic.co.uk/blog/colin/2011/11/property-finder-the-first-html5-based-windows-phone-7-application/
Hi,
I am an Android programmer and I’m venturing in C# world to make webapps to WP7 and I get confused with your solution for suppressing zoom and scrool interactions.
The C# is many different from Java and I will be honest, I do not understand how to implement your solution…
For example, I started a “Hello World” PhoneGap project and I added WebBrowserHelper.cs class and VisualTreeAdapter.cs class but I don’t understand where I call de utility class WebBrowserHelper in this project.
Is it asking too much if you could demonstrate it such as Property Finder, the PhoneGap-based application that you developed recently?
Hi … I will be publishing the Property Finder source soon, so you will be able to see it in use then.
Is probably one of those situations where the solution is right under your nose and you do not see it .. but .. I am very grateful if you could do that!
Thanks,
Kind Regards,
Since WP7 IE 9 does not support touchmove events http://blogs.msdn.com/b/iemobile/archive/2011/02/14/ie9-coming-to-windows-phone-in-2011.aspx
Could you intercept these pinch/pan calls and call them in JS with invokescript to provide a touch events polyfill for MS Surface like demos?
http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/
http://www.midemos.com/demos/iphone/touch/
I think this might be possible. Although, if you capture a manipulation event and feed it into your WebBrowser control, I am not sure how you then hit-test to find teh DOM element that should receive this event.
I think most touch enabled sites use document.elementFromPoint.
BTW: A little off topic, did you see jurassic (.net JS) now runs on mango http://jurassic.codeplex.com/SourceControl/changeset/changes/095f012e202a
Oh thanks. It works.
[...] Read original post by Colin Eberhardt at ScottLogic [...]
Hm, is it working only in Mango?
My project is still targeting WP OS 7.0, the Border’s events aren’t firing.
Any glues?
Yes, this will only work on Mango – the WebBrowser control in WP7.0 was quite different, it handles manipulation events internally – in the native layer, so there is no opportunity to intercept.
Hey, thanks for this!
I’ve been annoyed by pinching in WebBrowser but haven’t found a solution to disable it.