Introduction
In this article, I will explain how to convert a UIELement
to a JPEG image and print the UIElement
. Silverlight 4 supports printing UIElement
s. 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
".
<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.
ExtendedImage ei = ImageExtensions.ToImage(stkPanel);
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.
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);
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;
++_currentPage;
if (_currentPage < NoOfPages)
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.