Source code
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?
Silverlight 3 can accomplish these scenarios using the writeablebitmap API. writablebitmap between des a render method which can snag all of the pixels of a given UI element and place them into a buffer for manipulation. in this demo, I'll show how to take a "snapshot" of a Silverlight UI screen, upload the image to a Web server, and include it in a report Viewer (rdlc) report. you cocould easily modify these steps to save the snapshot to an image file on the server, or otherwise manipulate the pixels. view the demo the steps used in the demo are as follows: 1. Render the Silverlight UI to a writeablebitmap, passing in the UI element and an arbitrary transform. in the code below, the content of a canvas named cnvsource is rendered to the writeablebitmap. we pass in an empty translatetransform simply because one is required by the constructor:
WriteablebitmapBitmap =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 (IntY = 0; y <bitmap. pixelheight; ++ y) { For(IntX = 0; x <bitmap. pixelwidth; ++ X) { IntPixel = 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 (); |
NoteThat this PNG encoder does not include compression! This wowould Be A Good optimization to add, but also note that the gzipstream class is not present in Silverlight, So you wowould need to use an outside compression library such as sharpziplib.
3.At this point, we have the PNG bytes in a stream, and you cocould 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 future sion 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 calla 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. CES. Add (SRC ); Reportviewer1.localreport. Refresh (); |
That's it! I really think this use of writeablebitmap as a snapshot/print function will be useful in some of my projects that need to capture the current view of the Silverlight application.