Dear visitor, thanks for stopping by! If you want, you can follow all updates on Snowball.be via RSS. You can also follow me on Twitter or Facebook. More interesting posts from other Microsoft Regional Directors can be found at The Region.
Gill Cleeren     Silverlight     July 30, 2009    

Probably the most requested feature for Silverlight 3 was being able to print or export the contents of a control so that we can save it and then print it. While there is no Print class of some sort directly available in Silverlight 3 either, we can print, using some small workaround. And that workaround goes by the name of the WriteableBitmap.

In this sample, I have created a very simple DTP application (desktop publishing application). It allows the user to draw on a Canvas, add some text and some images. After that, he can print the result. There is room to improve, but it should get you on your way when trying to print from Silverlight 3.

This is the UI of the application.

image

Let’s take a look at how it was done. The XAML code for this sample is quite simple. The Canvas called DrawingCanvas is the one we want to export and print its contents.

            <Grid x:Name="GridApplication">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="150"></ColumnDefinition>
                    <ColumnDefinition Width="*"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="20"></RowDefinition>
                    <RowDefinition Height="*"></RowDefinition>
                </Grid.RowDefinitions>
                <Grid x:Name="GridHeader" Background="#47659e" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2">
                    <TextBlock Foreground="White" Margin="2, 0, 0, 0" FontWeight="Bold">
                    Printing from Silverlight 3
                    </TextBlock>
                </Grid>
                <StackPanel x:Name="ButtonStackPanel" Grid.Row="1" Grid.Column="0" Background="#efedeb">
                    <Rectangle Fill="Black" Height="40" Width="70" Margin="2"></Rectangle>
                    <Button x:Name="ButtonRectangle" Content="Add rectangle" Margin="3" Click="ButtonRectangle_Click" HorizontalAlignment="Center"  ></Button>
                    <Ellipse Fill="Black" Height="40" Width="70" Margin="2"></Ellipse>
                    <Button x:Name="ButtonEllipse" Content="Add Ellipse" Margin="3" Click="ButtonEllipse_Click" HorizontalAlignment="Center"></Button>
                    <Image Source="pictureicon.png" Width="70" Margin="2" Stretch="Uniform"></Image>
                    <Button x:Name="ButtonImage"  Content="Add image" Margin="3"  Click="ButtonImage_Click" HorizontalAlignment="Center"></Button>
                    <Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Center">
                        <TextBlock Text="T" FontSize="30" FontWeight="Bold" Margin="2" FontFamily="Courier New"  ></TextBlock>
                    </Border>
                    <Button x:Name="ButtonText" Content="Add text" Margin="3" Click="ButtonText_Click"  HorizontalAlignment="Center"></Button>
                    <Rectangle Height="1" Width="130" HorizontalAlignment="Center" Fill="DarkGray" Margin="5"></Rectangle>
                    <Button x:Name="ButtonCreate" Content="Create poster" HorizontalAlignment="Center" Click="ButtonCreate_Click"  Margin="3"></Button>
                    <Button x:Name="ButtonSave" Content="Save poster" HorizontalAlignment="Center" Margin="3" Click="ButtonSave_Click"></Button>
                </StackPanel>
                <Canvas x:Name="DrawingCanvas" Grid.Row="1" Grid.Column="1" Width="648" Height="578" Background="#bbbbbb">

                    
                </Canvas>
            </Grid>

As said, the class that makes printing possible, is the WriteableBitmap. We pass in the control we want to “render” and an arbitrary transform.

WriteableBitmap wb = new WriteableBitmap(DrawingCanvas, null);

Then, we use Joe Stegman’s PNG Encoder. It allows us to create PNG images on the fly. Note that, like mentioned on Joe’s blog, this encoder is not optimal and can be improved both in speed and compression size. We create an instance of the EditableImage class, giving it the size of the control we want to render.

editableImage = new EditableImage((int)DrawingCanvas.ActualWidth, (int)DrawingCanvas.ActualHeight);

At this point, we can start doing a pixel-by-pixel copy of the “canvas-data” to the EditableImage.

Converter cl = new Converter();
for (int idx = 0; idx < editableImage.Height; idx++)      // Height (y)
{
    for (int jdx = 0; jdx < editableImage.Width; jdx++) // Width (x)
    {
        if (wbCounter == wb.Pixels.Length)
            break;
        byte[] colorBytes = cl.ConvIntegertoByteArray(wb.Pixels[wbCounter], 3);
        editableImage.SetPixel(jdx, idx, colorBytes[0], colorBytes[1], colorBytes[2], 255);
        wbCounter++;
    }
}
The image data is now in memory, we can now export and print it using a simple stream and the Silverlight 3 SaveFileDialog.

SaveFileDialog dialog = new SaveFileDialog();
dialog.DefaultExt = "png";

if (dialog.ShowDialog() == true)
{
    using (Stream fs = (Stream)dialog.OpenFile())
    {
        Converter c = new Converter();
        c.CopyStreamContents(editableImage.GetStream(), fs);
        fs.Flush();
    }
}

The result is a generated PNG file, ready to print! The complete sample code can be downloaded here.

kick it on DotNetKicks.com
  Posted on: Thursday, July 30, 2009 9:20:26 PM (Romance Daylight Time, UTC+02:00)   |   Comments [2]
         
10/25/2014   5:27:51 AM
 Welcome to Snowball.be
Hello and welcome to snowball.be!

My name is Gill Cleeren, I'm a Microsoft Regional Director and an MVP ASP.NET.
On Snowball.be, you'll find all kind news and articles on .net, ASP.NET, WPF, Silverlight and Microsoft in general.
More on me can be found on my about page.

Should you have any questions, don't hesitate to contact me by Send mail to the author(s) .

 Partner sites
 Most popular tags
.net (124) .net 3.0 (6) .net 3.5 (18) .NET 4 (18) .NET Show (1) ADO.net (4) ASP.net (53) ASP.net AJAX (4) ASP.NET MVC (3) Atlas (12) Azure (2) Blend (2) Book (6) Book review (4) C# (43) Case studies (1) Chopsticks (3) Community (10) Community Day (16) Consoles (1) Database (1) DevDays09 (4) DotNetNuke (4) Efficiency (57) Enterprise Library (5) Events (62) Expression (7) Games (3) Hardware (9) Internet (18) IT (1) jQuery (1) LightSwitch (3) Links (11) LINQ (4) Mac (2) Metro (1) Microsoft (75) Mix 07 (6) Mix 08 (4) Mix 09 (1) Mix 11 (1) Movies (4) MVP (5) MVP Summit 2008 (3) mvvm (1) NDCOslo (1) Office 2007 (10) Other (8) PDC (22) PDC2008 (10) Personal (36) ppt (9) Programming (52) Programming tools (22) Regional Director (2) Silverlight (143) Silverlight Advent Calendar (24) sl4 (44) SL5 Data and Services Cookbook (2) Slide decks (13) Snowball (13) Software (20) Microsoft (25) Speaking (15) SQL Server (10) TechDays (13) TechEd (14) telerik (6) Telerik (6) TFS (1) Twitter (1) Vista (73) Vista Tricks (9) Visual Studio.net (38) Visug (33) VS2010 (8) Wallpaper (2) WCF (2) Webcasts (9) Webinars (5) Windows (41) Windows 7 (5) Windows 8 (3) Windows Azure (2) Windows Mobile (3) Windows Phone 7 (2) WinFX (17) WinRT (2) WP7 (2) WPF (40) XAML (24)

 On this page
 This site
 Archives
Navigation
 Sitemap
 Blogroll OPML
 Disclaimer

All content is property of www.snowball.be. Nothing on this site can be copied or published elsewhere, unless otherwise stated.

This site is made by Gill Cleeren.

Questions? Opinions? Send mail to the author(s) E-mail