Introduction
A pointedly absent feature in Silverlight 1 through 3 was the ability to print. What was the use of writing silverlight applications
if you couldn't use them to access the peripherals on your machine? Well now you can. Let's begin to look at this extremely
useful feature in the newest version of silverlight.
Installation Note
Creating your App
Let's start by creating a new silverlight application in 2010. Open a new project from the file menu and give your
silverlight application a relevant name.
Figure 1 - Creating the Silverlight Application to Demonstrate Printing
Double click on MainPage.xaml and start constructing the item you want to print using Silverlight components.
In my example, I've constructed a simple business card with logo and contact info just to give you an idea of how
to print a basic XAML form.
Figure 2 - The Application Design
We'll also add a button to the design to trigger the printing, but we'll place the button outside the visual tree
we wish to print. After quickly throwing together a sample from a myriad of Images and labels and running
the program, here is what we get:
Figure 3 - The Silverlight Business Card Application Running in the Browser
Now let's see how we can print out our work of art to a physical piece of paper.
It's all about the PrintDocument...Again
You may remember the PrintDocument when you were developing printing in Windows Forms. Things haven't changed
in the name of the class, but they have changed slightly in the approach Microsoft is taking when printing Silverlight apps.
The PrintDocument operates on the visual tree instead of a graphics object. It still has the PrintPage event, but instead
of drawing GDI+ commands to the printer (as in Windows Forms), you draw the Visual Tree. Actually you don't really
draw the visual tree persay. All you do is assign the part of the Visual Tree you want to print to the PrintPageEventArgs
PageVisual property inside the PrintPage event handler.
Most of the print functionality is self contained in the PrintDocument as it was in Windows Forms, so let us take a closer look
at the properties and methods of the PrintDocument class.
Propery or Method |
Description |
PrintDocument() |
Constructs a print document |
PrintedPageCount |
Number of Pages Printed |
Print |
Starts the printing process by bringing up the print dialog. |
BeginPrint event |
Occurs after the Print method has been called and the print dialog has
closed, but before the PrintPage handling occurs |
PrintPage event |
Occurs during the printing of each page |
EndPrint event |
Occurs after printing is completed or cancelled |
Table 1 - PrintDocument Members in Silverlight
As you can see, there is not much to the PrintDocument class. Some of the functionality for printing is divided among the event
arguements inside each event handler. The Print method kicks off printing and the BeginPrint, PrintPage, and EndPrint events allow
us to create event handlers to intercept printing before, during, and after the printing process respectively. For example, BeginPrint
can be used to put up an active window with a cancel button. EndPrint can be used to take the active window down. PrintPage is
where we do all the hard work of assigning the visual tree.
The PrintPage event handler takes a PrintPageEventArgs argument in which we can use to manipulate printing. Only two of the
properties are settable: HasMorePages and PageVisual, all of the rest of the properties are feedback from the framework.
We can use HasMorePages to indicate there is more of the Visual Tree to print that won't fit on the current page by setting it
to true in the PrintPage event handler. Or we can use HasMorePages to put different parts of the Visual Tree on different pages.
Member | Description | Type | Default |
HasMorePages | Set or get if the printer needs to print additional pages | bool | false |
PageMargins | The margins of the page being printed | Thickness |
|
PageVisual | The Visual Tree Element to Print | UIElement | null |
PrintableArea | Size of the Printable Area in Pixels | Size | 0.0, 0.0 |
Table 2 - PrintPageEventArgs Members
The Code
The code for printing the business card is fairly straightforward. In the example, we call the Print method on the PrintDocument
object to cause printing to happen from Silverlight. This triggers the 3 events we have mentioned BeginPrint, PrintPage, and EndPrint.
We don't do anything in BeginPrint in this sample to keep it simple. Inside of PrintPage, we assign the part of our Visual Tree that we
wish to send to the printer. In the example, the business card lies inside a border, so we send the Border control to the printer.
Below is the XAML for the border called AreaToPrint.
<Border x:Name="AreaToPrint" BorderThickness="1" Background="Beige" BorderBrush="Black">
The Border and everything inside it will be printed when it is assigned to the PageVisual property of the PrintPageEventArgs.
The EndPrint event handler just checks to see if anything went wrong during printing, and if something went wrong, it alerts
the user to the problem.
Listing 1 - Printing the Business Card in Silverlight Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Printing;
namespace UsingPrintingInSilverlight
{
public partial class MainPage : UserControl
{
// construct the print document for printing
PrintDocument printDocument = new PrintDocument();
public MainPage()
{
InitializeComponent();
// wire up all the events needed for printing
printDocument.BeginPrint += new EventHandler<BeginPrintEventArgs>(printDocument_BeginPrint);
printDocument.PrintPage += new EventHandler<PrintPageEventArgs>(printDocument_PrintPage);
printDocument.EndPrint += new EventHandler<EndPrintEventArgs>(printDocument_EndPrint);
}
void printDocument_EndPrint(object
sender, EndPrintEventArgs e)
{
// if an error occurred, alert the user to the
error
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
}
void printDocument_PrintPage(object
sender, PrintPageEventArgs e)
{
// assign the visual tree we want to print to
the event arg's PageVisual property
e.PageVisual = AreaToPrint;
}
void
printDocument_BeginPrint(object sender, BeginPrintEventArgs e)
{
// we don't do anything special here
}
private void
PrintButton_Click(object sender, RoutedEventArgs e)
{
// when the button is pressed, print the
business card
printDocument.Print("My Business
Card");
}
}
}
Running the Code
If we compile and run our application and press the button, the Print Dialog comes up. I chose the preview option
that came with my printer to demonstrate printing without having to waste paper (The printer prints the equivalent document).
As you can see, Silverlight has successfully called the printer from within the browser and allowed me to print my business card.
Figure 4 - Print Dialog Preview Called from Silverlight Application
Conclusion
Printing is one of the most awaited features in Silverlight and it is finally here in Silverlight 4.0. Its feature set
seems to be a little more limited than say Windows Forms, but it's good enough for most applications from
the browser and opens up a host of opportunities for writing rich printing applications on the web.
Anyway, if you have an inkling for some cool apps in Silverlight, don't hold back. Take advantage of the new features in
Silverlight and Visual Studio 2010 to test your creative ideas.