Click here to Skip to main content
11,805,035 members (61,155 online)
Click here to Skip to main content

Throttling Silverlight Mouse Events to Keep the UI Responsive

, 15 Jun 2010 CPOL 8K 8
Rate this:
Please Sign up or sign in to vote.
Throttling Silverlight Mouse Events to Keep the UI Responsive

If your Silverlight application performs intensive updates to the UI during mouse events, the UI can freeze because it is invalidated before it has a chance to render. This post describes a technique for ‘throttling’ mouse events to ensure that each time an event occurs, the UI has the opportunity to render.

Introduction – The Problem

The visual tree of a Silverlight / WPF uses the retained mode graphics  rendering style, where the tree forms a model of the graphics which are rendered to the screen. Any changes that are made to the visual tree by adding / removing objects or changing the properties of an object within the tree, are automatically rendered to your computer screen at some point in the future.

This graphics style makes the development of complex graphics far easier than with the immediate mode counterpart. You add objects, make changes to them, and these changes are reflected on the screen by some background magic. This works just fine most of the time, however, if you continually make changes to the visual tree, without yielding, the ‘process’ which updates the UI does not have the opportunity to run, and your UI is starved.

I have found that this problem occurs most often when handling mouse events, particularly MouseMove and MouseWheel. Both of these events have the opportunity to fire very rapidly. If, when handling one of these events you make some change to the visual tree, there is the possibility that the event may be raised again before these changes are reflected on the screen. For a demonstration of this, have a play with the following simple example:


[CodeProject does not support Silverlight content, see the above in action on my blog]

The application above creates funky patterns that track the current mouse position:

private void MainPage_MouseMove(object sender, MouseEventArgs e)
/// <span class="code-SummaryComment"><summary>

Everything works just fine when there are < 1000 lines on screen, however as more lines are added, the act of adding a new line to the visual tree becomes more expensive. As a result, the work needed to handle each event becomes so great that the UI is starved. If you move the mouse rapidly across the display, you will find that nothing happens until you stop moving your mouse, then all of a sudden the new lines appear.

Interestingly, the background animation (which is performed on the Tick of a DispatcherTimer) does not starve the UI.

Throttling – The Solution!

So, what to do? The answer is to throttle the event.

No, I don’t mean that kind of throttle, I mean throttle as in “to suppress or regulate the flow of”.

What we need to do is ensure that the changes we make to the visual tree within our MouseMove event are reflected in the UI before we make a subsequent change. Fortunately the Silverlight / WPF frameworks expose a static CompositionTarget.Rendering event which can be used for this purpose. This event is fired just before a frame is rendered. Therefore, to throttle the effect of the mouse event, we set a flag to indicate that we are waiting for a change to be rendered, then reset this flag just before rendering occurs.

I have wrapped this concept up in a simple class that provides a ThrottledMouseMove event:

/// <span class="code-SummaryComment"><summary>

The _awaitingRender flag ensure that we do not starve the UI. Note, the CompositionTarget.Rendering event handler removes itself after handling the event, this is because the presence of the handler causes Silverlight to continuously animate.

To use this code, simply substitute the regular MouseMove event handler with our throttled event:

// standard mouse move event handling
MouseHandler.MouseMove += new MouseEventHandler(MainPage_MouseMove);
// Replace with ...
// throttled mouse move event handling
var throttledEvent = new ThrottledMouseMoveEvent(MouseHandler);
throttledEvent.ThrottledMouseMove += 
	new MouseEventHandler(ThrottledEvent_ThrottledMouseMove);

As a result, the UI remains responsive:

[CodeProject does not support Silverlight content, see the above in action on my blog.]

Throttling the Mouse Wheel Event

The MouseWheel event is another mouse event that fires very rapidly and can result in the UI becoming frozen. Again, the same technique can be used to throttle this event. However, with the MouseMove event, the event arguments carry the current mouse position, the MouseWheel event carries just the mouse wheel position delta. If we simply suppress events that occur before render, the UI will not respond correctly, with a smaller delta being applied than is required.

The code shown below is a slightly more complex class for throttling the MouseWheel event. This class aggregates all the MouseWheel events that occur before the UI is rendered, supplying a total delta:

 /// <span class="code-SummaryComment"><summary>

The following application combines both of these throttled mouse event handlers:

[CodeProject does not support Silverlight content, see the above in action on my blog.]

You can download the full source for this blog post:

Regards, Colin E.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Colin Eberhardt
Architect Scott Logic
United Kingdom United Kingdom
I am CTO at ShinobiControls, a team of iOS developers who are carefully crafting iOS charts, grids and controls for making your applications awesome.

I am a Technical Architect for Visiblox which have developed the world's fastest WPF / Silverlight and WP7 charts.

I am also a Technical Evangelist at Scott Logic, a provider of bespoke financial software and consultancy for the retail and investment banking, stockbroking, asset management and hedge fund communities.

Visit my blog - Colin Eberhardt's Adventures in .NET.

Follow me on Twitter - @ColinEberhardt


You may also be interested in...

Comments and Discussions

-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.151002.1 | Last Updated 16 Jun 2010
Article Copyright 2010 by Colin Eberhardt
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid