One of the high-profile missing features in Silverlight has been Printing support. If you have ever tried to print a web page containing Silverlight content, what you saw on the printed page may be skewed or even missing altogether! So, what if you wanted to print a portion of your Silverlight screen, or take a “snapshot” image of the Silverlight UI to include in a report or other printable format?
WriteableBitmap bitmap = new WriteableBitmap(cnvSource, new TranslateTransform());
2.Convert the WriteableBitmap pixels to a PNG using Joe Stegman's PNG encoder.
EditableImage
imageData = new EditableImage(bitmap.PixelWidth, bitmap.PixelHeight);
for
(int y = 0; y < bitmap.PixelHeight; ++y)
{
for (int x = 0; x < bitmap.PixelWidth; ++x)
{
int pixel = bitmap.Pixels[bitmap.PixelWidth * y + x];
imageData.SetPixel(x, y,
(byte)((pixel >> 16) & 0xFF),
(byte)((pixel >> 8) & 0xFF),
(byte)(pixel & 0xFF),
(byte)((pixel >> 24) & 0xFF)
);
}
}
Stream
pngStream = imageData.GetStream();
|
NOTE that this PNG encoder does NOT include compression! This would be a good optimization to add, but also note that the GZipStream class is not present in Silverlight, so you would need to use an outside compression library such as SharpZipLib .
3.At this point, we have the PNG bytes in a stream, and you could take several approaches to get these bytes up to the server – such as using an Http Handler (ASHX). In this demo, we’ll place the bytes into a hidden field on the ASPX page and post the page back to the server for inclusion in a report. To do this, we’ll translate the PNG bytes into a string using Base64 encoding:
byte
[] binaryData = new Byte[pngStream.Length];
long
bytesRead = pngStream.Read(binaryData, 0, (int)pngStream.Length);
string
base64String =
System.Convert.ToBase64String(binaryData,
0,
binaryData.Length);
// save the encoded PNG bytes to the page
HtmlDocument
document = HtmlPage.Document;
HtmlElement
txtPNGBytes = document.GetElementById("txtPNGBytes");
txtPNGBytes.SetProperty("value", base64String);
// this calls a js function "postBackPrint" which will cause a postback
HtmlPage
.Window.CreateInstance("postBackPrint", new string[] { });
|
4.Now that we have our bytes up on the server, we can decode them and feed them to a ReportViewer (RDLC) report. This will give us a nicely printed format and the ability to export to PDF:
string
bytes64 = Request["txtPNGBytes"];
byte
[] imageBytes = System.Convert.FromBase64String(bytes64);
DSReportPrintImage
ds = new DSReportPrintImage();
DataRow
drImage = ds.Tables[0].NewRow();
drImage["ImageBytes"] = imageBytes;
ds.Tables[0].Rows.Add(drImage);
ReportViewer1.LocalReport.ReportPath = "ReportPrintSilverlight.rdlc";
ReportDataSource
src = new ReportDataSource("DSReportPrintImage_ImageData", ds.Tables[0]);
ReportViewer1.LocalReport.DataSources.Add(src);
ReportViewer1.LocalReport.Refresh();
|