I’ve been working on a pet project that does a lot of network I/O and database queries. One of the things I need to do is run long running things in the background – off the UI thread and keep the UI responsive. So, I’ve built a spinning busy state indicator. I’ve included the source code as well.
I’m still learning WPF. I started about two years ago (see my old posts) but was distracted by shipping a little thing we call Windows-7. Given our team is very likely to build some production WPF based products, I need to get back on the stick and learn the WPF basics.
As with any new project, I found several good examples on the ‘tubes. Sacha Barber’s example on CodeProject.com was a good start and where I got the inspiration for my basic graphical design. This one is similar, and this one is native on GDI+. Here is another one on the Expression Behaviors Gallery.
While all are good examples, I wanted to code my own completely from scratch. I had a few goals in mind:
Full support for styles and templates
Rotate in either direction
Could be disabled – like most other controls
Could be ‘spun’ manually –without an animation
This means I need to build a fully custom WPF control – a class that derives from System.Windows.Controls.Control. This turned out to be really easy – once I got past the learning curve!
Until recently, my WPF code and XAML were pretty klunky – the code seemed complicated to me and had a faint ‘just not right’ code smell. The more I looked at it, the riper it got. You can see some of this stinky cheese here. [ wow? was that really two years ago? I suppose that’s why they call shipping Windows-7 ‘work’ ]
In any case, I’ve had the time to do some hacking recently and I’ve learned a ton. One thing I’ve noted is there is a LOT more WPF information on the ‘tubes than there was two years ago, and the WPF MSDN Library documentation is way, way better. This made my recent efforts much easier.
The major thing I learned recently is that I had been going about WPF develop all wrong. All my previous hacks had been procedural in nature – doing the UI work in code. I hadn’t really groked how fundamental dependency properties and data binding are to WPF development. These simply are not framework features you can use – they are fundamental constructs. Tying things together with dependency properties and data bindings is just they way to do things in WPF. It took me a bit to grok it, but I had one of those ah-Ha! moments are few days ago. Groovy.
As with my other posts, I’m including the fully buildable source code. The code currently uses the .NET 3.5 Client Profile but it builds with Beta-2 of Visual Studio 2010. You can find the code attached.
The current code is fully functional. I’ve packaged the spinner its own assembly called Fenestra which Latin for ‘window’, clever huh? I’ve also included a developer framework (DF) that lets me test the control. It looks like this:
The DF lets me control the properties including the size, the spin rate and watch the events happen. Its very simple code. In the image above you can see two spinners, the one on the left is the default theme for the control. The one on the right is a templated and styled version.
All of the elements are fully style-able. Each item in the spinner is a WPF Shape which means their key attributes can be bound to the control’s dependency properties.
I drew the fundamental shapes in Expression Design 3 which has a learning curve all its own. I used it because it directly produces XAML. Once I got the basic knack of using the tool, it wasn’t too hard to do. You can find the original design files in the BizzySpinnerDF directory. They are named Circles.design and Rectangles.design.
Installing and building the project is easy: Just download and run the installer. It will put the project on your desktop. Note, it doesn’t really ‘install’ anything – there are no shortcuts and it doesn’t write to the registry. You can move the sample directory wherever you would like, or just delete it when you are done. No un-installing is needed. Also note that the contents are licensed with the Microsoft Public License.