SharpGIS

#GIS from a .NET developer's perspective

Add MouseWheel scrolling to Silverlight's DataGrid

In my previous post, I wrote about how you could add MouseWheel scrolling to the ScrollViewer using a simple behavior. I wanted to have the same MouseWheel scroll on the DataGrid, and thought that it could be done the exact same way.

However, it turns out that the DataGrid is not using a ScrollViewer, but instead used a Virtualized panel that is re-rendered every time a ScrollBar is scrolled. Unfortunately the DataGrid only reacts to the Scroll event of the ScrollBar, and not it’s Value property (not sure why they did it like this), so it’s not just a matter of finding the ScrollBar and increase the value. If I did that, the ScrollBar would move, but the DataGrid would not update. In fact the only way to raise the Scroll event was to click the ScrollBar, but I wanted to do this in code so I can’t really “click” something.

Fortunately Silverlight has a UIAutomation framework, that allows you to simulate user interaction. This is great for running automated tests against your controls, where you want to simulate a user clicking and typing inside your application. This got me thinking that the way to raise the Scroll event was simply to use the UIAutomation framework to virtually ‘click’ the ScrollBar. So in other words, each time you scroll down, the code ‘clicks’ the down button in the ScrollBar, and vice versa. While this simulated click approach works well, there’s an even simpler way, since the DataGrid’s Automation allows for calling scroll, which is what I’ll be using here.

The first step is to get a reference to the AutomationPeer of the DataGrid:

AutomationPeer automationPeer = FrameworkElementAutomationPeer.FromElement(this.AssociatedObject);

Since the automation peer for the DataGrid implements the IScrollProvider pattern, we can simply request that pattern and call Scroll() to scroll the DataGrid:

IScrollProvider scrollProvider = automationPeer.GetPattern(PatternInterface.Scroll) as IScrollProvider;
ScrollProvider.Scroll(ScrollAmount.NoAmount, ScrollAmount.SmallIncrement);

The rest is trivial for the DataGrid MouseWheel behavior. On the MouseWheel event of the DataGrid we call the Scroll method with either a SmallIncrement or SmallDecrement, and the DataGrid will scroll one row. It’s not as smooth as the ScrollViewer implementation in the previous blogpost, but at least it allows us to use the MouseWheel to scroll the rows. Since most scrollable controls in Silverlight already has UIAutomation and IScrollProvider support, this behavior will also work on other scrollable controls, and not only the DataGrid.

So here’s what it looks like in XAML when you included a reference to the behavior assembly:

<data:DataGrid x:Name="datagrid" Height="100" >
	<i:Interaction.Behaviors>
		<behaviors:MouseScrollBehavior/>
	</i:Interaction.Behaviors>
</data:DataGrid>

I’ve updated the source code for my Behavior library, and also updated the sample application to include the DataGrid.