Introduction
Silverlight currently does not support mouse wheel events. However, you can attach an event to capture the mouse wheel movement through the HtmlPage object, find the control beneath the mouse position with the VisualTreeHelper class and scrolling the region (DataGrid, Combobox, ScrollViewer, TreeView, etc) through the Automation API.
Source Code and Live Demo
Mouse wheel event
There are several examples on the net how to capture the mouse wheel event. The following code snippet shows this very shortly. You can find a full example here (Thanks to Mike Snow): http://silverlight.net/blogs/msnow/archive/2008/07/29/tip-of-the-day-23-how-to-capture-the-mouse-wheel-event.aspx
public TestPage() { InitializeComponent(); HtmlPage.Window.AttachEvent("DOMMouseScroll", OnMouseWheel); HtmlPage.Window.AttachEvent("onmousewheel", OnMouseWheel); HtmlPage.Document.AttachEvent("onmousewheel", OnMouseWheel); } private void OnMouseWheel(object sender, HtmlEventArgs args) { // code goes here… }
Scrolling with the UI Automation API
As next step we have to implement programmatically scrolling for different types of controls, such as Combobox, Treeview, DataGrid, ItemsControl, ScrollViewer, etc. But how do we programmatically scroll those controls without implementing special derived classes from it. Furthermore the scrolling support for the DataGrid is unfortunately not implemented by using ScrollViewers to do scrolling. Instead the DataGrid implements a method called ScrollIntoView which is not really helpfully here.
As I played with the Silverlight UI Automation API (UIA), I found a very interesting interface called IScrollProvider. This interface is exposed through the UIA and enables us scrolling out of the box. The UIA Provider interfaces are meant for Screen readers and general automation (testing) but can equally be used at runtime.
// get automation peer AutomationPeer automationPeer = FrameworkElementAutomationPeer.FromElement(element); if (automationPeer == null) { // create automation peer for element automationPeer = FrameworkElementAutomationPeer.CreatePeerForElement(element); } // try to get scroll provider IScrollProvider scrollProvider = automationPeer.GetPattern(PatternInterface.Scroll) as IScrollProvider; if (scrollProvider != null) { scrollProvider.Scroll(horizontalScrollAmount, verticalScrollAmount); }
That’s it!
Connect wheel event to the controls
How do we route the mouse turned event to the right control? You can implement the code above for every control where we need mouse scrolling and enable/disable it with the MouseEnter/MouseLeave event. But this brings us a lot of plumbing code and special controls.
The VisualTreeHelper class provides the method FindElementsInHostCoordinates. This method returns a list of UIElements beneath a specified point (the current mouse position).
Our mouse wheel class (see sample code here) always knows the current mouse position througth the subscribed MouseMove event on the root UIElement.
Here the code (reduced to the important lines):
// go through all element beneath the current mouse position IEnumerable<UIElement> elements = VisualTreeHelper.FindElementsInHostCoordinates(currentPoint, s_rootElement); foreach (UIElement element in elements) { // get automation peer (if already created for this control) AutomationPeer automationPeer = FrameworkElementAutomationPeer.FromElement(element); if (automationPeer == null) { // create automation peer for element automationPeer = FrameworkElementAutomationPeer.CreatePeerForElement(element); } //expect null: some elements doesn't have an automation peer implemented if (automationPeer != null) { // try to get scroll provider IScrollProvider scrollProvider = automationPeer.GetPattern(PatternInterface.Scroll) as IScrollProvider; if (scrollProvider != null) { if (scrollProvider.VerticallyScrollable) { scrollProvider.Scroll(ScrollAmount.NoAmount, scrollAmount); // break the further search in the uielement collection break; } // don't break here, because of encapsulated scroll viewers such as in the treeview from the sl-toolkit //break; } } }
Misc
With pressing the control key, horizontal scrolling is possible also:
// horizontal scrolling? bool ctrlKey = (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control; if (scrollProvider.HorizontallyScrollable && ctrlKey) { scrollProvider.Scroll(scrollAmount, ScrollAmount.NoAmount); }
Conclusion
The UIA (UI Autamation API) provide an eas way to do scrolling without extending the existing controls and the VisualTreeHelper gets the possibility to dispatch the mouse wheel-turned event to the right control.
Most of the controls with scrolling regions implements the IScrollProvider API, unfortunately Textbox not. I’m trying to get another way to enable scrolling for textbox.

This is just what I was looking for. It looks like the source code zip file is missing the MouseWheelScrollingWeb project – any chance you can update the zip file?
Thanks!
By: Brian on August 24, 2009
at 2:19 pm
Hi Brain,
Maybe the link is broken… you can download the solution here:
http://files.thekieners.com/blogcontent/MouseWheelScrolling/MouseWheelScrolling.zip
Thanks!
Beat
By: beatkiener on August 24, 2009
at 2:27 pm
Got it – thanks!
By: Brian on August 24, 2009
at 2:34 pm
Sorry, I misunderstood your question.
Of course, the web project is missing, but you should be able to start the Silverlight project directly. Visual studio will create a TestPage.html on the fly.
By: beatkiener on August 24, 2009
at 2:37 pm
How to change this so it works in SL3 OOB application also ? Shoudl this changed to use SL3 OnMouseWheel events ?
By: Andrus on August 24, 2009
at 3:57 pm
Hi Andrus,
I just changed the implementation to the UIElement.MouseWheel event to work in OoB.
It works fine, expect the combobox doesn’t.
http://files.thekieners.com/blogcontent/MouseWheelScrolling/MouseWheelScrollingSL3.zip
If I will find time I will research the combobox problem or if you have an idea please leave a comment.
Thanks,
Beat Kiener
By: beatkiener on August 25, 2009
at 9:32 am
beatkiener,
Thank you very much! This is by far the most elegant and useful solution I have seen to this problem. Bravo.
rogueiv
By: RogueIV on August 25, 2009
at 10:20 pm
Using Ctrl+Wheel for horizontal scrolling is nice idea.
How to add zoom it / zoom out feature for a scrolling with ctrl+shift+wheel presses just like Internet Explorer Ctrl ++ / – or Ctrl+wheel command ?
By: Andrus on August 27, 2009
at 3:45 pm
I think one way is to use a ScaleTransform for zooming in/out the a specify element of the application.
I’ve just added the following code to the MouseWheelService class and it works pretty good.
// zoom? bool zooming = ctrlKey && (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift; if (zooming) { // go through all element beneath the current mouse position IEnumerable elements = VisualTreeHelper.FindElementsInHostCoordinates(currentPoint, s_rootElement); foreach (UIElement element in elements) { IMouseWheelZoom mouseZooming = element as IMouseWheelZoom; if (mouseZooming != null) { mouseZooming.OnMouseWheelZooming( new MouseWheelZoomingEventArgs(currentPoint, e.Delta)); break; } } } else { // normal.... }The code searches for a UIElement beneath the current mouse position which implements the interface IMouseWheelZoom. In this way you can simply delegate the functionality to any UIElement which implement IMouseWheelZoom. You can find a quick implementation of IMouseWheelZoom in the Page.cs file.
Here is the code: http://files.thekieners.com/blogcontent/MouseWheelScrolling/MouseWheelWithZooming.zip
Cheers,
Beat Kiener
By: beatkiener on August 27, 2009
at 6:50 pm
Nice but not sure is this useful: If DataGrid is zoomed, its scrollbars move out of screen. How to force only Text inside DataGrid to zoom so that DataGrid scrollbars remain visible ?
By: Andrus on August 28, 2009
at 6:17 pm
Thank you very much for this code. It works very nice and I don’t think I could have figured it out myself.
Would be nice for MouseWheel scrolling to be natively supported on the microsoft silverlight controls, but this works nicely.
By: Joshua Smyth on August 31, 2009
at 5:20 am
[...] How to enable mouse wheel scrolling in Silverlight without extending controls [...]
By: Mouse wheel behavior with native UIElement MouseWheel event « Kiener's Blog on September 4, 2009
at 5:25 pm
How can I scroll all the datagrid whenever I am scrolling any one of the datagrid in my xaml page?
I have 3 Datagrid on my xaml page and whenever user scrolls first datagrid then other 2 datagrid also scroll.
Thanks
By: Varsha on October 5, 2009
at 9:54 am
Hi,
Sorry for delay, I was very busy last days. Did you find a solution to parallel scroll all three data grids?
I think there are two cases:
First case is when the user scrolls a data grid with mouse wheel. In that case you can grab the IScrollProvider from each data grid and delegate your scroll command to all there grids.
In the second case the user manually drags the scrollbar. In that case you can grab a reference to the vertical scrollbar and delegate the scroll event to the two other data grids and scroll them via IScrollProvider.
I didn’t try this out, but I would start with this class:
public class MyDataGrid : DataGrid { private ScrollBar verticalScrollbar; public MyDataGrid() { } public override void OnApplyTemplate() { base.OnApplyTemplate(); verticalScrollbar = base.GetTemplateChild("VerticalScrollbar") as ScrollBar; verticalScrollbar.Scroll += new ScrollEventHandler(verticalScrollbar_Scroll); } void verticalScrollbar_Scroll(object sender, ScrollEventArgs e) { // Here access the two other data grids an scroll them via IScrollProvider IScrollProvider datagrid2 = null; // todo // scroll based on the scroll origin switch (e.ScrollEventType) { case ScrollEventType.First: datagrid2.SetScrollPercent(System.Windows.Automation.ScrollPatternIdentifiers.NoScroll, 0); // 0% break; case ScrollEventType.LargeDecrement: datagrid2.Scroll(System.Windows.Automation.ScrollAmount.NoAmount, System.Windows.Automation.ScrollAmount.LargeDecrement); break; case ScrollEventType.LargeIncrement: datagrid2.Scroll(System.Windows.Automation.ScrollAmount.NoAmount, System.Windows.Automation.ScrollAmount.LargeIncrement); break; case ScrollEventType.Last: datagrid2.SetScrollPercent(System.Windows.Automation.ScrollPatternIdentifiers.NoScroll, 100); // 100% break; case ScrollEventType.SmallDecrement: datagrid2.Scroll(System.Windows.Automation.ScrollAmount.NoAmount, System.Windows.Automation.ScrollAmount.SmallDecrement); break; case ScrollEventType.SmallIncrement: datagrid2.Scroll(System.Windows.Automation.ScrollAmount.NoAmount, System.Windows.Automation.ScrollAmount.SmallIncrement); break; case ScrollEventType.ThumbPosition: case ScrollEventType.ThumbTrack: case ScrollEventType.EndScroll: double percent = e.NewValue / this.verticalScrollbar.Maximum; datagrid2.SetScrollPercent(System.Windows.Automation.ScrollPatternIdentifiers.NoScroll, percent); break; default: break; } } }By: beatkiener on November 6, 2009
at 6:21 am
This code doesn’t work when the application is in full screen mode. Any ideas?
By: John Doe on October 30, 2009
at 1:39 am
Hi,
No. But I’m going to check it….
By: beatkiener on November 6, 2009
at 6:26 am
Hi, thanks for the reply but I want the scrolling for both Horizontal as well as Vertical. Can we do this?
Thanks again.
By: Varsha on November 8, 2009
at 6:16 pm
Hi,
How do you make this work in full screen mode?
By: Nits on January 29, 2010
at 9:53 pm
Hi neetaupadhyay84,
In SL2 there was no native MouseWheel support from the UIElement. The implementation was based on a javascript handler and because of security restriction javascript is not allow in FullScreen mode.
In SL3 the MouseWheel event is now supported from the UIElement class. Check out my new version for SL3 which is using the native UIElement.MouseWheel event to do the scrolling. This implementation works in FullScreen mode and in Out of Browser mode as well.
Check out this: http://files.thekieners.com/blogcontent/MouseWheelScrolling/MouseWheelScrollingSL3.zip
There is just one gap with the combobox control. Please consider to read the following post too: http://blog.thekieners.com/2009/09/04/mouse-wheel-behavior-with-native-uielement-mousewheel-event/
Best regards,
Beat Kiener
By: beatkiener on February 9, 2010
at 10:49 am
Very sweet, Kiener. Thanks for taking the time to share this.
By: Mike on February 8, 2010
at 8:52 pm