Peregrine's View

Yet another C# / WPF / MVVM blog …

WPF General

WPF Controls – Busy Spinner

You Spin me Right Round Baby, Right Round

Having completed the series on MVVM, the next few post will feature some of the UI controls that I’ve developed to complement the standard WPF classes.

The first is relatively simple – a busy spinner (otherwise known as a progress ring). There are already many implementations of this type of control published, but I’ve come across quite a few that either consume way too much in the way of system resources, or fail to switch off when they are no longer active / displayed.

My version of the control consists of a Canvas object containing a group of ellipses, laid out in a circle. Each ellipse has the same fill value – bound to the foreground of the control, but with a different opacity value to provide the variation in display characteristics. There’s no reason why you have to use a SolidColorBrush for this value – any other Brush type can be used if you want to get really creative. Note that UseLayoutRounding is set to false for this canvas, otherwise the ellipses will appear to wobble as the spinner rotates, due to the WPF rendering adjusting their calculated position to the closest whole pixel. The canvas is held within a Viewbox control, which scales it to fit within the control boundary.

The spinning action is controlled by a DispatcherTimer. This is preferred to System.Timers.Timer in WPF applications due to potential threading issues. Each tick of the timer updates the Angle value of the RotateTransform on the canvas, so that each ellipse advances by one spot. Note how the timer is activated from the IsVisibleChanged event. The covers both the direct setting of the spinner’s own Visibility property, and also the indirect case where the spinner is placed inside another visual container which itself is collapsed or hidden. To activate the spinner, just make it visible.

The demo project for this post shows the spinner in action. The visibility property of the spinner is bound to the IsExecuting property of the async relay command – which saves the need to have an additional flag property. Note how the button state is automatically set to disabled (due to perRelayCommandAsync.CanExecute returning false) while the command is being executed.

The next post will introduce another new control, but something a little more complicated this time.

As usual the code samples for this blog are available on Github, along with my own personal C# / WPF library.

If you find this article useful, or you have any other feedback, please leave a comment below.

4 thoughts on “WPF Controls – Busy Spinner

  • George Yefchak

    I don’t see the demo code, but rather three separate class library projects for the View, ViewModel, and Model. (This seems very odd.) I can build all three projects, but I don’t know how to actually put the spinner in a WPF app.

    • Hi George
      If you look in the Blog folder of the Github repository, you’ll find demo projects corresponding to each blog post, including the one for the busy spinner. If you download or clone the entire repository then you’ll get the code for all of the demo projects and the library.

      The reason for the three different WPF class library projects is to emphasise the clean separation between each of the three layers of an MVVM based application.


Leave a Reply

Your email address will not be published. Required fields are marked *