Printing Visiblox Charts
17 May 2011 by Jesse Beaumont
A question we get a lot from our customers is “Does Visiblox Charts provide support for printing?”. Well the answer is yes, you can print Visiblox Charts using the standard WPF and Silverlight printing APIs.
In this post we’re going to take a look at printing with Visiblox Charts. I’m going to focus on the Silverlight platform. However, I will make some comments about using Visiblox Charts in WPF printing at the end as well.
Printing In Silverlight
There are already lots of articles out there on the web about how to use the printing capabilities provided by the framework. If you need more information on that I suggest you check out this for Silverlight and this for WPF, or any of the many other resources to be found out there on the subject.
Here we’re just going to concentrate on the Visiblox Charts part of the story.
Visiblox Charts and Printing
Let’s start by having a button which will invoke our print functionality. That button’s hander will look like this:
private void Button_Click(object sender, RoutedEventArgs e) { PrintDocument printDocument = new PrintDocument(); printDocument.PrintPage += new EventHandler<PrintPageEventArgs>(printDocument_PrintPage); printDocument.Print("Visiblox Print Demo"); }
This just constructs a new PrintDocument and attaches a PrintPage handler to it. Then it invokes the print method to actually perform the printing. The printDocument_PrintPage method is where we’re going to do all the heavy lifting. So lets take a look at that.
private void printDocument_PrintPage(object sender, PrintPageEventArgs e) { // We need to disable the deferred invaliation as we // don't want to be bound to the render cycle // (This is a Visiblox specific step) InvalidationHandler.ForceImmediateInvalidate = true; // Build the chart instance with dimensions set // (note that it's not in the visual tree). Chart chart = BuildChart(); double fullWidth = e.PrintableArea.Width; double fullHeight = e.PrintableArea.Height; ; Grid grid = new Grid() { Height = fullHeight, Width = fullWidth }; grid.RowDefinitions.Add( new RowDefinition() { Height = new GridLength(75) }); grid.RowDefinitions.Add( new RowDefinition() { Height = new GridLength(fullHeight - 75) }); var title = new TextBlock() { Padding = new Thickness(0, 10, 0, 0), Text = "Newly Constructed Chart", TextAlignment = TextAlignment.Center, FontSize = 16, FontWeight = FontWeights.Bold }; Grid.SetRow(title, 0); Grid.SetRow(chart, 1); grid.Children.Add(title); grid.Children.Add(chart); e.PageVisual = grid; // Turn deferred invalidation back on // (This is a Visiblox specific step) InvalidationHandler.ForceImmediateInvalidate = false; }
Basically, this method just creates a Grid with two rows, the first containing a title and the second containing a chart. It’s pretty plain and simple. The only slight oddity is this line:
InvalidationHandler.ForceImmediateInvalidate = true;
So what’s that about? Well by default Visiblox Charts provides some deferred invalidation functionality to make sure rendering happens at the last possible moment. In a user interface context that is what you want because it means fewer render cycles overall to get the chart on screen, but in a printing context where there are no render cycles we need to force the chart to render immediately. That is exactly what that line does. Remember to make sure and unset that at the end of your printing code again otherwise you will notice a performance degradation in your UI.
For completeness sake there is one piece missing which is the BuildChart method. That looks like this:
private Chart BuildChart() { Chart chart = new Chart(); chart.Series.Add(new LineSeries() { LineStrokeThickness = 3 }); DataSeries<double, double> ds = new DataSeries<double, double>(); for (int i = 0; i < 100; i++) { ds.Add(new DataPoint<double, double>(i, i * i)); } chart.Series[0].DataSeries = ds; chart.LegendVisibility = System.Windows.Visibility.Collapsed; return chart; }
This just creates a new chart with a single line series plotting y = x^2. Of course, this could really be any Visiblox Chart instance, even one that is currently rendered on screen.
Here’s what the output looks like on a printed sheet.
That’s it. It really is as simple as that. If you want to try it out you can download the code here. Just add a reference to Visiblox Charts which you can download from here and off you go.
Visiblox Charts and Printing in WPF
Finally, lets just take a quick look at WPF. The main difference between printing a chart in Silverlight and printing a chart in WPF is actually the printing API itself. The WPF and Silverlight APIs are not the same. However, once you get a handle on the WPF API it’s pretty much the same as above. The one caveat is that if you aren’t printing a chart that is already in the visual tree (i.e. currently on screen), you will need to manually invoke the Measure and Arrange calls. To do that you could add the following code after you’ve added the chart to the grid but before you print:
double chartWidth = fullWidth; double chartHeight = fullHeight - 75; Size chartSize = new Size(chartWidth, chartHeight); // Manually invoke the render cycle so that the template is applied chart.Measure(chartSize); chart.Arrange(new Rect(0, 0, chartWidth, chartHeight));
Other than that, it’s the same as before.
Summary
In this post we took a quick look at printing a Visiblox Charts. As you’ve seen it really is pretty straightforward and doesn’t need much in the way of extra code. The one trick is to make sure you set the ForceImmediateInvalidate to true before you print and back to false after. Happy Printing!
