As part of my recent Windows Presentation Foundation user group tour, I’ve been doing a quick demo showing how easy it is to go in WPF from a bare-bones textual presentation to a rich visual presentation of the same data. To me, this is one of the big opportunities that WPF opens up for “ordinary” application designers, those of us living in a world where we don’t have a team of professional graphic designers dedicated to making our application look more like a car advert than a computer program. So I wanted to put together a set of demos showing how to get from the traditional “chuck it in a list box or data grid and move on to the next feature” textual UI to a simple but effective visualisation UI in a series of small and easy to grasp steps.
The motivating example I’m going to use is visualising earthquake data. This has got an obvious geographical presentation, marking up events on a map and using colour, shape and/or size to show intensity. But we’re going to start from what WPF gives us for free, and work towards the geographical presentation one step at a time.
So let’s assume we have a collection of Quake objects, and let’s plug them into a list box.
Okay, that doesn’t look so great.
Of course, the problem here is that WPF has no idea how to render a Quake object. The best it can do is call ToString on each one, and since I haven’t overridden ToString, that just returns the type name. One way to address this, obviously, is to override ToString, but that brings its own problems: what should the returned string look like? Will that be appropriate wherever and whenever somebody wants to display a Quake in a list? What about localisation? Besides, ToString is a dead end as far as visualisation is concerned: there’s no way a method that returns strings can help us to come up with the geographical presentation described above.
The right way to solve this is to use a data template. The data template tells WPF how to display a particular object. Data templates allow the application to decide how it wants to render the Quake object in any given circumstance — unlike ToString, which bakes the rendering into the object itself — and enables different applications, or different parts of the same application, to render the same object in different ways according to the user’s needs.
We’ll start with a simple data template, consisting of a horizontally-oriented StackPanel containing a bunch of TextBlocks.
That’s a lot better. It’s still a plain textual representation, but at least now we can see some actual information.
We’re still not really helping the user to visualise the information. We need to use things like colour and size to supplement the text, so that the user can get an overview more easily and can quickly transfer their attention to whatever events they find particularly interesting.
A WPF data template allows us to include things other than text, and to set properties other than the textual content. We can, for example, add an Ellipse whose Width and Height are data-bound to the magnitude of the earthquake. Bigger earthquakes will have bigger circles and will therefore stand out more. We could also bind the font size to the magnitude, further emphasising the big quakes.
The display could do with being spruced up graphically, but conceptually it’s clear that we’ve managed to supplement the plain text with a visual representation. Now, however, the list box presentation itself is becoming a limiting factor.
Windows Presentation Foundation controls are “lookless.” That is, the control defines a behaviour, independent of its display. What we think of as the “look” of a control is actually just the default template, and we can replace that if we have a different requirement.
In the case of a list box, the behaviour of a list box is to display a collection of items and track which one is (or which ones are) selected. By default, it displays those items one above the other in a big vertical stack, but there’s nothing inherent in the description of a list box’s behaviour that ties it to a big vertical stack. And indeed the WPF list box allows us to replace this default display via the ItemsPanel property.
For a geographical presentation, we need a panel that allows us to place items at coordinated positions. In WPF, that’s the Canvas panel type. We’ll set the background of the canvas to be a map.
We also need to update our data template again, to bind the Canvas.Top and Canvas.Left attached properties so that the items are positioned correctly on the canvas. Unfortunately, there’s a small wrinkle here. Defining and binding these properties on the item data template doesn’t achieve anything. The reason for this is that our template instantiations are actually getting wrapped in ListBoxItem controls, and it’s these ListBoxItems that are being placed on the Canvas. We need to set the Canvas attached properties on the ListBoxItems, not the data template, and to do this we have to use the ListBox.ItemContainerStyle property.
Once we do that, the members of the list appear positioned in the list box according to their geographical location.
This is the breakthrough! Our users will now find it much easier to see the set of earthquakes as a whole and to visualise the relationships between them. The nicest thing about this is that it is still a working ListBox — all the mouse hit testing, keyboard navigation, selection tracking etc. is still taken care of for you even though the visuals are so dramatically different from what we expect in a ListBox.
(Incidentally, the code as supplied incorrectly displays the quakes with their top left at the epicentre, instead of centred on it. This is easily fixed; I didn’t bother because it’s not particularly germane to the idea of the visual presentation.)
We can still go a little bit further. At the moment we are using a single template for all earthquake events. With our data set, that’s okay, but if we had a lot more little earthquakes then we’d end up with a lot of “noise” on the graph, making it hard to see the significant quakes. We could partly solve that with a more complicated data template and some new converters — say, making the relationship of circle size to magnitude non-linear, and binding the visibility of the caption to the magnitude so it’s hidden for small quakes — but this is fiddly and limited, and loses our intent in a maze of detail.
What we really want is a way to say that different quakes may have different representations, and to capture in a central location our criteria for choosing between them. This is what a template selector gives us. So in our final step, instead of having one template, we’ll have three templates, and instead of specifying the template via the ItemTemplate property, we’ll specify a selector via the ItemTemplateSelector property. Our selector is pretty simple — it just checks whether the magnitude is below an “insignificance” or above a “megacatastrophe” threshold, and chooses the small, normal or big template accordingly.
Of course, with graphic design like this, there will be some who will argue that I should have stopped with the textual representation.
How much effort is involved in building something like this in WPF? This demo would probably take an hour or two to build from scratch for a knowledgeable WPF developer, assuming you already had a suitable data model (which is a reasonable assumption for a line of business type application), and that there was no argument about or fiddling around with the actual design itself. It would take a bit longer to sand down some of the rough edges. You can imagine that many visualisations such as Gantt charts would be equally quick, and some such as scatter graphs could be even quicker.
As I’ve said elsewhere, I don’t buy the argument that WPF is primarily for high-end graphical applications and that it’s an inappropriate choice for business applications. The combination of data binding, lookless controls and the unified programming model for text, controls and graphics makes WPF an enormously productive platform for anything that goes even a little way beyond the “GUI green screen.” Once the business managers and the usability folks realise how cheaply they can have it, data visualisation is going to be one of the killer applications for WPF.