Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Silverlight 4 - Converting to image and printing a UIElement in multiple pages

0.00/5 (No votes)
2 Sep 2011 1  
Silverlight 4 printing restricts any control to print in a single page, leaving the remaning portion. This is a workaround for that.

Introduction


In this article, I will explain how to convert a UIELement to a JPEG image and print the UIElement. Silverlight 4 supports printing UIElements. But it will print content only in a single page. If the control's content is big enough to fall in multiple pages, then we cannot get the subsequent pages to print. In this article, I will explain how to get rid of this problem. The simple idea is to convert the UIElement to image. Then splitting the image to multiple pages and sending them to the printer one by one.


Using the code


The first step is to design your XAML.


In this example, I'm going to print the StackPanel called "stkPanel".


XML
<StackPanel x:Name="stkPanel" Orientation="Vertical" Grid.Row="1">
      <Image Source="jawahar.jpg" Width="500" Height="400"/>

      <TextBlock Text="Silverlight - Printing a huge control in multiple pages 1"/>
      <TextBlock Text="Silverlight - Printing a huge control in multiple pages 2"/>
      <TextBlock Text="Silverlight - Printing a huge control in multiple pages 3"/>
      <TextBlock Text="Silverlight - Printing a huge control in multiple pages 4"/> </StackPanel>

In the code-behind, inside the Print button event, first convert the UIElement to an image.


C#
ExtendedImage ei = ImageExtensions.ToImage(stkPanel); //stkPanel - Control that you want to print

The next thing we need to do is get the printer's printable area. Then use that to divide the image to multiple pages till it reaches the end of the image.


C#
void pd_PrintPage(object sender, PrintPageEventArgs e)
{
    int printableAreaHeight = Convert.ToInt32(e.PrintableArea.Height);
    int printableAreaWidth = Convert.ToInt32(e.PrintableArea.Width);
    int ActualImageHeight = ei.PixelHeight;
    int ActualImageWidth = ei.PixelWidth;
    int NoOfPages = (ActualImageHeight / printableAreaHeight);
    if ((ActualImageHeight % printableAreaHeight) > 0)
        NoOfPages += 1;
    images = new List<ExtendedImage>();
    ImageTools.Rectangle rt;
    int xCoordinate = 0;
    int yCoordinate = 0;
    int rectangleHeight = 0;
    for (int i = 0; i < NoOfPages; i++)
    {
        if (i > 0)
        {
            yCoordinate = printableAreaHeight * i;
        }
        if ((i + 1) == NoOfPages)
        {
            if ((ActualImageHeight % printableAreaHeight) > 0)
                rectangleHeight = (ActualImageHeight % printableAreaHeight);
            else
                rectangleHeight = printableAreaHeight;
        }
        else
        {
            rectangleHeight = printableAreaHeight;
        }
        rt = new ImageTools.Rectangle(xCoordinate, yCoordinate, 
                 ActualImageWidth, rectangleHeight);
        //slices the image to multiple images(multiple pages) and adds to an images list
        images.Add(ExtendedImage.Crop(ei, rt)); 
    }

    var bitmapImage = new BitmapImage();
    bitmapImage.SetSource(images[_currentPage].ToStream());

    var imageBrush = new ImageBrush();
    imageBrush.ImageSource = bitmapImage;
    var rectangle = new System.Windows.Shapes.Rectangle
    {
        Width = bitmapImage.PixelWidth,
        Height = bitmapImage.PixelHeight,
        Fill = imageBrush
    };
    e.PageVisual = rectangle; //sets the pagevisual to print
    ++_currentPage;
    if (_currentPage < NoOfPages) //Checks if there are more pages to print
        e.HasMorePages = true;
}

Then start the priniting. Inside the PrintPage event, assign the split image one by one to the PageVisual property of the PrintEventArgs. Set the HasMorePages property to true till it reaches all the pages. Isn't this simple?


In this example, I printed a StackPanel element which contains an image and more than 200 lines of text. If we print this element without my code, only half of the StackPanel gets printed. Using my code will resolve this problem. My code will convert the element to an image and split the image to fit multiple print pages.


Note


In this article, I just gave an idea of how to print a Silverlight UIElement in multiple pages. But you can customize the print view on your own.


History


  • 2nd September, 2011: Initial post.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here