It's already almost a year ago when I found out about Google Chart API. I used it for my year ending post of 2007. I haven't done anything useful with Google Chart API after this post. But I'd like to experiment, so I thought what about an integration between Silverlight and the Google Chart API.
Integration
The integration is a very slim line. Just a HTTP Get to an Uri that follows the specs in the Google Chart API. The documentation consists of the following parts:
But all I used was basically the example on the API front page:
http://chart.apis.google.com/chart?cht=p3&chd=t:60,40&chs=250x100&chl=Hello|World
This example contains the following parts: Chart Type, Chart Data, Chart Size and Chart Labels.
How I want it to work?
I want to be able to do a very simple thing in the Silverlight application. No logic about how the integration is done, is a very important idea. I also have the meaning that we should not have to use a special control to view a chart, just because we already have an Image control for viewing an image. A chart is not that much more than an image, isn't it?
1 var chartData = new GoogleChartData
2 {
3 Size = new Size(400, 200),
4 Type = ChartType.Pie3d,
5 Labels = {"Silverlight", "Flex"},
6 Data = {"20", "80"},
7 Title = string.Format("RIA's{0}Compared", Environment.NewLine)
8 };
9
10 chartImage.SetValue(HeightProperty, chartData.Size.Height);
11 chartImage.SetValue(WidthProperty, chartData.Size.Width);
12
13 chartImage.Source = googleChartBuilder.ConvertFrom(chartData);
Set up the chart data in lines 1 to 8. After this I want to make sure the target image control has the same dimensions as set in the chart data. Then run the GoogleChartBuilder to convert the data to an image.
The inner workings
The GoogleChartData class is just a data structure class.
1 public class GoogleChartData
2 {
3 public GoogleChartData()
4 {
5 Data = new List<string>();
6 Labels = new List<string>();
7 }
8
9 public IList<string> Data { get; set; }
10 public IList<string> Labels { get; set; }
11 public Size Size { get; set; }
12 public ChartType Type { get; set; }
13
14 public string Title { get; set; }
15 }
The logic is divided in two classes, one for constructing any uri you can think of, the other one for transforming the GoogleChartData into a querystring dictionary. The UriBuilder is very simple just ensures that the first part is preceded by a ?-character and the next parts are preceded by the &-character.
1 public class UriBuilder : IUriBuilder
2 {
3 public Uri Build(string baseUri, string page, IDictionary<string, string> queryString)
4 {
5 if(string.IsNullOrEmpty(baseUri) && string.IsNullOrEmpty(page))
6 throw new Exception("baseUri and/or page should be provided.");
7
8 UriKind kind;
9 if (string.IsNullOrEmpty(baseUri))
10 kind = UriKind.Relative;
11 kind = UriKind.Absolute;
12
13 var uriBuilder = new StringBuilder(string.Concat(baseUri,page));
14 if(queryString!=null && queryString.Count >0)
15 {
16 char separatorCharacter = '?';
17 foreach (var queryPart in queryString)
18 {
19 uriBuilder.Append(separatorCharacter);
20 uriBuilder.Append(queryPart.Key);
21 uriBuilder.Append('=');
22 uriBuilder.Append(HttpUtility.UrlEncode(queryPart.Value));
23
24 separatorCharacter = '&';
25 }
26 }
27 return new Uri(uriBuilder.ToString(), kind);
28 }
29 }
Now for the part that's responsible for the translation of the GoogleChartData into an uri.
1 public class GoogleChartBuilder : IGoogleChartBuilder
2 {
3 private readonly IUriBuilder uriBuilder;
4
5 public GoogleChartBuilder(IUriBuilder uriBuilder)
6 {
7 this.uriBuilder = uriBuilder;
8 }
9
10 public BitmapImage ConvertFrom(GoogleChartData googleChartData)
11 {
12 IDictionary<string,string> queryString = new Dictionary<string, string>();
13
14 //ChartSize
15 queryString.Add("chs",string.Format("{0}x{1}",googleChartData.Size.Width,googleChartData.Size.Height));
16
17 //ChartType
18 if(googleChartData.Type == ChartType.Pie3d)
19 queryString.Add("cht","p3");
20
21 //Labels
22 if (googleChartData.Labels != null && googleChartData.Labels.Count > 0)
23 queryString.Add("chl",string.Join("|", googleChartData.Labels.ToArray()));
24
25 //Data
26 if (googleChartData.Data != null && googleChartData.Data.Count > 0)
27 queryString.Add("chd", string.Concat("t:",string.Join(",", googleChartData.Data.ToArray())));
28 //Title
29 if(!string.IsNullOrEmpty(googleChartData.Title))
30 queryString.Add("chtt",googleChartData.Title.Replace(" ","+").Replace(Environment.NewLine,"|"));
31 return new BitmapImage(uriBuilder.Build("http://chart.apis.google.com/", "chart", queryString));
32 }
33 }
This isn't that difficult and translates into something like the following.
This solution is not done at all, it's just a proof-of-concept of the integration of Silverlight and the Google Chart API. You can download the sources here.