If you haven't had a look at the Google Chart API I definitely recommend you do so. It can be a good, light alternative to investing in a more complete charting package. And honestly, most of the extra stuff offered by the 3rd party charting components out there is just eye candy that detracts from the information you chart should communicate.
So, with the Google Chart API you can easily put charts like this in your web application or page:
All you need to do is put an img on your page, and set it's src to a url that contains some Google Chart magic. The url for the chart above looks like this:
Granted, the query arguments are quite complex. But Google has some nice documentation for it, and in the end it's not so bad. Here's a simple example:
The url for this puppy is:
The way you talk to Google Chart is through a series of parameters, separated with an ampersand (&). The url above contains three parameters, as follows:
| cht=lc |
Set the chart type to line chart. |
| chs=150x100 |
Set the size of the chart to a width of 150 and a height of 100. |
| chd=t:10,70,50,40,80,5,25,95 |
The data points for the chart, as comma-separated values. |
So, as you can see, pretty simple stuff.
But what about using this in desktop applications, and WPF applications in particular? Since all Google Chart does is generates an image based on parameters you pass to it in the URL, it can be used in XAML through the Image control. Like this:
<Image Width="150" Height="100" Source="http://chart.apis.google.com/chart?cht=lc&chs=150x100&chd=t:10,70,50,40,80,5,25,95"/>
Note that the ampersands (&) had to be encoded as "&" in the XAML.
Here's a screenshot of the XAML above being used in a little application:
Ok, so that works nicely. But dealing with the url, and in particular passing the data point for the chart to the API that way is a little bit ugly, and certainly feels very crude compared to how you usually do things in WPF. So what can be done to improve this? One thing that comes to mind is using a value converter to convert a list of values to the url-format that Google Chart wants. Here's an example of that:
[ValueConversion(typeof(IList), typeof(string))]
public class ListToTextEncodingConverter : IValueConverter
{ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{ IList valueList = (IList)value;
string baseUrl = (string)parameter;
if (valueList == null || baseUrl == null)
return string.Empty;
string valueString = "";
CultureInfo usCulture = new CultureInfo("en-us");
foreach (object item in valueList)
{ double? val = item as double?;
if (val.HasValue)
{ if (valueString.Length > 0)
valueString += ",";
valueString += val.Value.ToString(usCulture.NumberFormat);
}
}
return baseUrl + "&chd=t:" + valueString;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{ return Binding.DoNothing;
}
}
It accepts something that implements IList, and tries to find doubles in it, and constructs the url string from that. In addition it accepts the rest of the parameters for Google Chart as a parameter.
And here's a snippet of XAML that uses that value converter to display a chart:
<Window x:Class="WpfSample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfSample"
xmlns:converters="clr-namespace:WpfSample.ValueConverters.ChartDataEncodingConverters"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<local:SampleData x:Key="SampleData"/>
<converters:ListToTextEncodingConverter x:Key="ListToTextEncodingConverter"/>
</Window.Resources>
<Grid>
<Image Width="250" Height="150"
Source="{Binding Source={StaticResource SampleData}, Converter={StaticResource ListToTextEncodingConverter}, ConverterParameter='http://chart.apis.google.com/chart?cht=lc&chs=250x150&chds=0,30'}"/>
</Grid>
</Window>
Oh, and please not that the ConverterParameter seems to screw up the WPF designer in Visual Studio 2008, I haven't looked into whether anything can be done about that. But it compiles and runs fine.
SampleData is just a set of values, you could of course use whatever you want for your data source, perhaps pull something from a database and use Linq to project it into a list of double values. Here's the class that creates the sample data:
public class SampleData : List<double>
{ public SampleData()
{ Add(10);
Add(20);
Add(15.2);
Add(12);
Add(21);
Add(17);
Add(11);
Add(8);
Add(12);
Add(18);
}
}
Here's what the application looks like:
Simple, but I guess you get the idea.
And finally, is it bad to use a web-based API for charting in a desktop application? Not really, in my opinion. Most desktop apps need to talk to servers anyway, and grabbing a few charts over the web is not going to be a significant performance issue.
Oh, one more thing. Of course this works great in Silverlight 2.0 as well.