Silverlight Printing API

, Silverlight Printing API


Silverlight 5 Supports Vector Printing

.Printing API



" In Silverlight 4, printer support was added with the use of bitmap printing. In Silverlight 5, a more suitable vector printing model was used and it was made the default printing mode."

  • Silverlight 4 uses bitmap printing which sends data to the printer rendered as a grapic using the WriteableBitmap class. It has been surmised that bitmap printing was used in Version 4 so Microsoft could quickly get the printing function into Silverlight. However, bitmap printing is not really appropriate for text. Bitmaps contain large amounts of data which make the printing slower and uses more memory than vector printing. The bitmaps are optimized for screen display with dithering; this causes a fuzzy appearance on text when it is printed. Text inside a bitmap is not selectable, so it is not good for printing to a PDF. Silverlight's bitmap printing is unlike printer languages (PCL, Postscript) that create a small print job and allow the printer to control the printing according to its own capabilities. Instead, Silverlight bitmap printing always prints at 600 dpi. The application needs to control sizing to prevent clipping so the application needs to create the appropriate size elements. Silverlight considers 1px to be 1/96 of an inch. So, 768px width = 8 inches, and 960 px height = 10 inches. For Silverlight 4 an option is to use COM automation and generate a report using Microsoft Word or Excel.

  • Silverlight 5 contains vector printing which is its default print mode. This is a more suitable model for printing reports, but the printing capabilities in Silverlight are limited. An application written in a native language would typically use the operating system API, however Silverlight does not. Using the Silverlight printing classes the application has to control several aspects of the printing, such as page breaks, keeping track of the position within the data, printing dimensions, print previews, and using headers/footer. A print element can be created using XAML (virtual print document) which can help reduce the amount of work required by the application.

  • Silverlight printing is asynchronous as it runs on a background thread. However the events are fired on the UI thread so this could impose some blocking.

Printing Classes

  • The PrintDocument and PrintPageEventArgs classes are use to print the desired UIElement.

  • The PrintDocument class contains:
    • Methods:
      1. Print - displays the standard print dialog box. If the print is approved from the dialog box, then the BeginPrint event, and then the PrintPage events are raised. The print method is asynchronous, however it raises events on the UI thread which may cause it to be blocked. Untrusted applications must call the Print method from inside a user-initiated event. The method takes one string parameter which identifies the print job; the string will be a description of the print job when displayed in the print spooler.
    • Properties:
      1. PrintedPageCount - gets the number of pages sent to the print driver. This may not be the actual number of pages actually printed because of the printer lag. The count is incremented after each PrintPage event.
    • Events:
      1. BeginPrint - fires once for each print job. It fires after the Print method is called and the print dialog box successfully returns, but before the PrintPage event is raised.
      2. PrintPage- fires once for each page printed. The print content is assigned in this event. This is also where layout information may be obtained and used in creating the print layout. It passes an PrintPageEventsArgs class that is specific to each page printed.
      3. EndPrint - fires once for each print job. It fires when the printing operation is passed to the print spooler or when the print operation is cancelled by the application author.
    • The PrintPageEventArgs class contains:
      • Properties:
        1. PageVisual- specifies UI element to be printed. Can be an on-screen or off-screen element. (e.g. Layoutroot, imgCathy, etc). Off-screen elements can be specifically designed for printing. Typically the UIElement will be a container element like a Panel, which can contain more than one UI element.
        2. HasMorePages - gets or sets a Boolean value indicating whether the printing should stop after the current page.
        3. PrintableArea- gets a Size object indicating the height and width of the available print area. Content printed outside this rectangular area will be clipped. To prevent clipping, a scale transform can be applied to the UIElement to shrink down to the page size.
        4. PageMargins - gets a Thickness object indication the margins of the current page.

Example of Printing an Image Element

  • Shown below is an example of a simple print application which only prints a single UIElement (an Image). Note that lambda notation is used for the event handler, so the PrintPageEventArgs class is implicit.
,Printing an Image


Simple Printing Example

public partial class MainPage : UserControl
{
    private PrintDocument myPrintDocument;

    public MainPage()
    {
        InitializeComponent();
        myPrintDocument = new PrintDocument();
    }

    private void btnPrint_Click(object sender, RoutedEventArgs e)
    {
        myPrintDocument.PrintPage += (s, ea) =>
        {
            ea.PageVisual = imgCathy;
            ea.HasMorePages = false;
        };
        myPrintDocument.Print("Cathy's Picture"); 
    }

Example of Hiding Screen Element During Printing

  • Shown below is an example of printing the entire screen (LayoutRoot Element) with the button being hid during the print.
,Printing Without Hiding the Button


Printing Without Hiding the Button

,Printing With the Button Hid


Printing With the Button Hid

public partial class MainPage : UserControl
{
    public MainPage()
    {
        InitializeComponent();
    }

    private void btnPrint_Click(object sender, RoutedEventArgs e)
    {
        PrintDocument myPrintDocument = new PrintDocument();
        myPrintDocument.PrintPage += new EventHandler<PrintPageEventArgs>(myPrintDocument_PrintPage);
        myPrintDocument.BeginPrint += new EventHandler<BeginPrintEventArgs>(myPrintDocument_BeginPrint);
        myPrintDocument.EndPrint += new EventHandler<EndPrintEventArgs>(myPrintDocument_EndPrint);
        myPrintDocument.Print("Cathy's Picture"); 
    }

    void myPrintDocument_PrintPage(object sender, PrintPageEventArgs e)
    {
        e.PageVisual = LayoutRoot;
    }

    void myPrintDocument_BeginPrint(object sender, BeginPrintEventArgs e)
    {
        btnPrint.Visibility = Visibility.Collapsed;
    }

    void myPrintDocument_EndPrint(object sender, EndPrintEventArgs e)
    {
        btnPrint.Visibility = Visibility.Visible;
    }
}



Reference Articles


Top