PDF for Silverlight
What's New Features Pricing Updates Maintenance
PDF for Silverlight: What's New
Leveraging the power of Silverlight to view PDF documents and forms (Updated for Silverlight 3 and Silverlight 4)
Using Microsoft Silverlight, developers can provide their users with content-rich web applications which can now include complex graphics and better interaction with users. Amyuni PDF for Silverlight provides the ability to display high quality PDF documents that are easily readable by users, compared to displaying documents as Jpeg images.
Now that PDF has become the standard format for document storage and form processing in most corporations, your Silverlight applications can benefit from the ability to natively serve PDF documents and forms.
PDF for Silverlight Paper
Requirements (Server Side)
The server-side code that converts the document into XAML and builds the ZIP package is very straight-forward (built into a HttpHandler) and uses the Amyuni PDF Creator .NET:
Requirements (Client Side)
Any web browser running on any operating system with the Silverlight control versions 3.0 or higher. The sample PDFSilverlightControl will be automatically downloaded to the client by the Silverlight framework. No additional components need to be downloaded or run on the client PC.
At first glance, viewing PDF documents within a Silverlight control looked like a 15-minute job. It would be sufficient to convert the PDF document into an XPS, which is a derivative of XAML, feed the XPS to the Silverlight control, add some bells and whistles and we were done. Converting a PDF, or any document for that matter, into an XPS can easily be achieved with the Amyuni PDF Creator; all that was needed is a way to feed the XPS into the Silverlight control. We were, however, faced with a number of challenges:
Silverlight supports reading only a single XAML file. There is no mechanism by which one can feed multiple pages separately, nor is there a way to feed all the resources such as images and fonts used by that page. Silverlight provides no neat way of packaging a document the same way PDF and XPS do but requires all bits and pieces of a document to be created separately on the server and downloaded programmatically using the calling application. This precludes the ability to dynamically stream a document from a server to a client, which is a basic requirement of most applications.
Another area that had been developed is in the Amyuni PDF Creator control running on the server side. The PDF Creator control feature that returns a XAML file, used to operate on the source PDF file in its entirety and then return XAML for all of the pages in the file. When a PDF file is fairly large, this process is lengthy, and the client side application would just have to wait without progress notification until the server starts writing back the response to the client. Version 4.5 of the Amyuni PDF Creator control can return a subset of the total pages in the original document instead of returning all of the pages at once in the XAML file. This can be controlled by setting the “PageSequence” Document attribute to an array of pages that are requested or “PageSequenceStr” to a string representation of pages requested.
The image object provided by Silverlight is limited in that it does not allow for inline image data. The only way to specify the source for an image is by using a URL. To extract an image from a PDF and set it as the source for a Silverlight image object would require extracting the image into a temporary file on the server and setting the source of the image as the temporary URL - a solution that is not feasible in any real-life situation.
The basic requirements for building a document viewer using Silverlight are:
The ability to feed each page separately to account for large documents and prevent having to download the whole document to the client PC before viewing it
The ability to package page resources such as images and fonts within the document without having to store and retrieve the resources from the server
The ability to use fonts that are not installed on the client PC but are embedded within the source document
The ability to send additional information known as document metadata to the client
Using the WebClient Object and the Application.GetResourceStream() method
In Silverlight 3 and Silverlight 4, the combination of WebClient object and the static Application.GetResourceStream() method provided us with the solution to problem of retrieving a zip package from a web server and extracting each object separately on the client in the Silverlight user control. The WebClient downloads a XAML zip package that is prepared by the PDF Creator control on the server side. The downloaded zip package is stored in as a Stream in a member variable of our acPDFSilverlightControl class.
Within the ZIP package, each page description can is stored as a separate XAML file and all resources used by that page stored in a virtual folder.
Downloading the ZIP package and extracting objects from it can be asynchronous and the ZIP package dynamically created on the server and streamed back to the client without resorting to temporary files, is exactly what we needed. The basic syntax for using the WebClient object is as follows:
public void LoadFromUrl(string url)
// Retrieves the XAML of document packaged in a ZIP format located at the specified URL
// which can be something like:
// "http://www.amyuni.ca/PageTurnPdf/pdf.asp?PDFFile=doc.pdf" or
// start web download using the WebClient object
Uri uri = new Uri( url );
WebClient webClient = new WebClient();
webClient.AllowReadStreamBuffering = true; //speeds application response time
// add event listener to detect when data is available
// add event handler for catching download progress notifications
// start request
private void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
// Start loading the document
// e.Result will contain the XAML ZIP Stream
m_zipStream = e.Result;
// get XAML of document
Stream stream = GetPartFromZipPackage("Document/document_1.fdoc", m_zipStream);
StreamReader sreader = new StreamReader(stream);
string sDoc = sreader.ReadToEnd();
// get XAML of page from the ZIP package
Stream stream = GetPartFromZipPackage("Pages/page_" + (pageNumber + 1).ToString() +
// convert to string
StreamReader sreader = new StreamReader(stream);
string sPageXaml = sreader.ReadToEnd();
Extracting and Rendering Images
Downloading the XAML description of the page to the client is not sufficient to display the images. An additional step is needed to loop through all the image objects and set the source for every image to one of the images in the ZIP package. Each time a new page is loaded, “ProcessElements” is called. This function searches for all images on a page and sets their “ImageSource” attribute:
private void ProcessElements(object _elems)
// process all page elements to set:
// - the source of all image elements
// - the font of all text elements
for ( int i = 0; i < elems.Count; i++ )
UIElement elem = elems[i]; //a child UIElment
Image img = elem as Image;
// the Source would be a string
if (img.Source != null && img.Source.ToString() != "")
var src = img.Source;
if (src != null)
string s = src.ToString();
// set the source after removing the leading slash
Stream stream =
BitmapImage bitmap = new BitmapImage();
img.Source = bitmap;
// loop recursively through all children of the current element
Accurately positioning and rendering of text elements proved to be trickier than graphics and images. PDF provides a number of ways for defining text encodings and font types. Both XPS and XAML are limited to Unicode text and XAML provides much less flexibility than its counterparts for rendering text. To alleviate text issues, Amyuni PDF components provide the developers with methods to optimize the text content of a page and convert all text to Unicode. The “OptimizeDocument” method is used on the server to optimize text content before attempting to render it in a Silverlight control:
' Optimize the document to line level in order to improve the XAML export
When the font used in the source document is not available on the client PC, Silverlight would substitute with a different font which usually gives results that are not satisfactory. Silverlight provides a mechanism for specifying the font used to display a specific element, as long as the font is in OpenType or TrueType format. The Downloader object can be used in this case to package all the fonts used by the document. The fonts are embedded in the ZIP package as partially embedded fonts that are not usable by the end-user in order to avoid font licensing issues.
In parallel to the image processing described above, the sample viewer loops through all text objects and sets the font source for each object to be one of the fonts in the ZIP package:
// set the font source for all text elements to fonts retrieved from the ZIP package
if ( elem.GetType() == typeof(TextBlock) )
TextBlock tb = (TextBlock) elem;
// set the FontSource
tb.FontSource = new FontSource( m_zipStream );
The text element’s “FontFamily” attribute maps the text’s font to one of the fonts packaged in the ZIP file. This is done automatically by the Silverlight component when the requested font is not located on the end-user’s system.
Server Side Scripts
The server-side code that converts the document into XAML and builds the ZIP package is very straight-forward and uses the Amyuni PDF Creator .NET:
<%@ WebHandler Language="C#" Class="PdfHandlerNet" %>
using System;using System.Web;
[WebService(Namespace = "http://www.amyuni.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class PdfHandlerNet : IHttpHandler
public void ProcessRequest (HttpContext context)
context.Response.ContentType = "application/x-zip-compressed";
var strFilePath = context.Request.QueryString["PDFFile"];
var strPages = context.Request.QueryString["Pages"];
// Create the PDF Creator ActiveX object
// This will throw an exception if the control is not installed
// or the document not found
var acpdf = Activator.CreateInstance<Amyuni.PDFCreator.IacDocument>();
//Use a valid evaluation license code
acpdf.SetLicenseKey("Silverlight Evaluation", "1234..3445");
FileStream fIn = new FileStream(context.Server.MapPath(strFilePath),
// Set the page sequence. If QueryString("Pages")
//did not find that parameter, then strPages will be ""
//and setting the attribute will clear the array of pages
acpdf.Attribute("PageSequenceStr").Value = strPages;
// Optimize the document to line level in order to improve the XAML export
// return the XAML attribute of the document object which is a ZIP package
var o = acpdf.Attribute("XAML").Value;
public bool IsReusable
Expanding the Sample to View Documents other than PDF
The server-side script can easily be expanded in order to render other types of documents. To render XPS documents, the document should be loaded by the PDF Creator control and saved back into XAML to make it compatible with Silverlight. This can be done by replacing the PDF file with an XPS in the server-side script.
To render other types of documents, they should be first converted into PDF using the Amyuni PDF Converter, then streamed back to the client as a ZIP package.
The PDF Converter product is available for download from: http://www.amyuni.com/en/developer/pdfconverter.
A sample for converting documents into PDF on a server can be found at: http://www.amyuni.com/en/resources/technicalnotes/
Direct conversion of HTML to PDF and XAML