Studio Enterprise 2010 v3 includes the new C1PdfViewer control - the first of its kind - for viewing PDF documents in Silverlight and WPF. This viewer has its own built-in PDF parser so it has no dependency on Adobe Reader. It's considered to be experimental in this first release, because not every feature of PDF is supported out of the box (for example: special fonts and input controls are not supported yet).

The Story


ComponentOne is also well known for PDF generating components for .NET. The C1PdfDocument control is an advanced PDF-generating component which you can use to create dynamic PDFs from your C# or VB.NET code. You can use C1PdfDocument to create new PDFs in code and then directly save these or preview them in C1PdfViewer. From C1PdfViewer, end-users can directly save and print the PDF. You can also take existing PDF documents, not created from C1PdfDocument, and view them in C1PdfViewer (so long as they don't contain unsupported content).

So with the addition of C1PdfViewer you can now create and preview PDFs in your applications!

The Sample


In this section I will walk through creating a very simple Silverlight sample for generating, previewing and exporting a document such as an invoice. I will use C1PdfDocument to generate the invoice, piece by piece, and then use C1PdfViewer to preview the document to the end-user. The user will also have the option to directly save the invoice as PDF without previewing it first.



Creating the PDF


First, initialize a new C1PdfDocument in code. I have organized all the pdf-generating code into a single method called CreateInvoice.

//instantiate c1pdfdocument
C1PdfDocument _c1Pdf = new C1PdfDocument();

public MainPage()
{
InitializeComponent();
CreateInvoice();
}

The CreateInvoice method draws all the content to the document. With methods such as DrawString, DrawLine and DrawImage, we are able to create rich documents quite easily.

private void CreateInvoice()
{
Rect _pageRect = _c1Pdf.PageRectangle;
_pageRect.X = 72;
_pageRect.Y = 72;

//page settings
Font largeFont = new Font("Arial", 36);
Font mediumFont = new Font("Arial", 18);
Font smallFont = new Font("Arial", 14);
int spacing = 20;

//draw text to pdf
string text = "Invoice";
_c1Pdf.DrawString(text, largeFont, Colors.Black, _pageRect);
Size sz = _c1Pdf.MeasureString(text, largeFont);
_pageRect.Y = sz.Height spacing;

//draw image from resources to PDF
BitmapImage bi = LoadBitmap("c1ball.jpg");
var wb = new WriteableBitmap(bi);
Rect imgRect = new Rect(450, 40, 80, 80);
_c1Pdf.DrawImage(wb, imgRect);

//draw line to pdf
_c1Pdf.DrawLine(new Pen(Colors.Black, 2.0), new Point(72, _pageRect.Y), new Point(504, _pageRect.Y));
_pageRect.Y = spacing;

//render order information
text = "Order #150001";
_c1Pdf.DrawString(text, mediumFont, Colors.Black, _pageRect);
sz = _c1Pdf.MeasureString(text, mediumFont);
_pageRect.Y = sz.Height spacing;
text = "Item #301246";
_pageRect.X = 120;
_c1Pdf.DrawString(text, smallFont, Colors.Black, _pageRect);
text = "$0.00";
_pageRect.X = 450;
_c1Pdf.DrawString(text, smallFont, Colors.Black, _pageRect);
sz = _c1Pdf.MeasureString(text, smallFont);
_pageRect.Y = sz.Height spacing;
text = "Item #158824";
_pageRect.X = 120;
_c1Pdf.DrawString(text, smallFont, Colors.Black, _pageRect);
text = "$0.00";
_pageRect.X = 450;
_c1Pdf.DrawString(text, smallFont, Colors.Black, _pageRect);
sz = _c1Pdf.MeasureString(text, smallFont);
_pageRect.Y = sz.Height spacing;
_pageRect.Y = spacing;
_c1Pdf.DrawLine(new Pen(Colors.Black, 1), new Point(120, _pageRect.Y), new Point(504, _pageRect.Y));
_pageRect.Y = spacing;
text = "TOTAL:";
_pageRect.X = 120;
_c1Pdf.DrawString(text, smallFont, Colors.Black, _pageRect);
text = "$0.00";
_pageRect.X = 450;
_c1Pdf.DrawString(text, smallFont, Colors.Black, _pageRect);
sz = _c1Pdf.MeasureString(text, smallFont);
_pageRect.Y = sz.Height spacing;

//Add new page
_c1Pdf.NewPage();
_pageRect.Y = 72;
_pageRect.X = 72;
_c1Pdf.DrawString("Second Page", smallFont, Colors.Black, _pageRect);
}

Saving and Previewing the PDF


Add two buttons to the page, along with a C1PdfViewer control.




<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Button Content="Save Invoice" Name="btnSaveInvoice" Click="btnSaveInvoice_Click" />
<Button Content="Preview Invoice" Name="btnPreviewInvoice" Click="btnPreviewInvoice_Click" />
</StackPanel>
<c1pdfviewer:C1PdfViewer Name="c1PdfViewer1" Grid.Row="1" Background="#FF969696" />
</Grid>

The first button will be simply for saving the invoice to the users machine through a SaveFileDialog. We don't have access to the local file system on the users machine through a Silverlight application unless we use a SaveFileDialog. The following code can be used to save the selected file as PDF using the C1PdfDocument.Save method.

private void btnSaveInvoice_Click(object sender, RoutedEventArgs e)
{
//save file using dialog
SaveFileDialog sfd = new SaveFileDialog();
sfd.DefaultExt = ".pdf";
bool? sfdResult = sfd.ShowDialog();
if (sfdResult.HasValue &amp;&amp; sfdResult.Value)
{
using (Stream s = sfd.OpenFile())
{
_c1Pdf.Save(s);
}
}
}

When the user clicks the Preview Invoice button, we load the PDF into the C1PdfViewer. The C1PdfViewer control has a LoadDocument method which takes a stream. Since we don't want to force the user to first save the document through a SaveFileDialog, instead we save the file to isolated storage and then open a stream directly to it. The code below uses the application store from isolated storage to save the PDF file to one stream and then immediately opens the file using a new stream. If you need to keep track of many files, you may want to consider using the IsolatedStorageSettings dictionary.

private void btnPreviewInvoice_Click(object sender, RoutedEventArgs e)
{
//save file to isolated storage
IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
Stream s = new IsolatedStorageFileStream("MyInvoice.pdf", FileMode.OpenOrCreate, FileAccess.ReadWrite, isf);
_c1Pdf.Save(s);
s.Close();
//open file in c1pdfviewer
s = isf.OpenFile("MyInvoice.pdf", FileMode.Open);
c1PdfViewer1.LoadDocument(s);
s.Close();
}

That concludes this simple sample. You can download the full sample here. Download Studio Enterprise or Studio for Silverlight to get the C1PdfViewer and C1PdfDocument controls necessary to run the sample.