Subscribe to:

The Kiwi's TaleWitchBlasterDerelict Blow Stuff Up

Easy landscape printing in Silverlight

I know this isn't normally what I post about here, but I thought someone on the web might find it useful.

I struggled in vain to find a simple solution to printing landscape view in Silverlight, but I managed to come up with one that only takes a few lines of code:

 

 

            var printDocument = new PrintDocument();

            printDocument.PrintPage += (s, r) =>

                                           {

                                               r.PageVisual = this.LayoutRoot;

                                               var transformGroup = new TransformGroup();

                                               transformGroup.Children.Add(new RotateTransform(){Angle = 90});

                                               transformGroup.Children.Add(new TranslateTransform() {X = r.PrintableArea.Width});

                                               LayoutRoot.RenderTransform = transformGroup;

                                           };

This simple Lamda method, which assumes that you want to print the layout root of the page (Although there shouldn't be a reason why it can't print any element on the page), applies two transforms. The first is simply to rotate the whole layout root 90 degrees. The reason why this alone isn't enough, is that by default the layout root will rotate on it's top left corner, so when you rotate it 90 degrees the body of the page moves left (Imagine rotating a page on a cork board with a pin through the top left corner). The second transform is to correct this by moving the page by the width of the printable area to the right.

After you have finished printing, you will want to move everything back so that it still renders to screen correctly.

 

            printDocument.EndPrint += (s, r) =>

                                          {

                                              var transformGroup = new TransformGroup();

                                              transformGroup.Children.Add(new RotateTransform() { Angle = 0 });

                                              transformGroup.Children.Add(new TranslateTransform() { X = 0});

                                              LayoutRoot.RenderTransform = transformGroup;

                                          };

Hope this helps

 

EDIT: Martin Lottering has offered the suggestion below for resolving an issue where the sides of the page may be cut off:

If you battle to get the landscape printing working properly because it cuts off:

Use a `canvas` container control, and **rotate** the control **inside of the canvas**.

After many hours of pure frustration, I finally decided to put the thing inside of a canvas. Voila!! No more cut off.

Have a look at the following SMALL test application to demonstrate. It is just a page with print button.

 

    using System.Windows;

    using System.Windows.Controls;

    using System.Windows.Media;

    using System.Windows.Printing;

    using System.Windows.Shapes;

 

    namespace SilverlightApplication1 {

 

        public partial class MainPage : UserControl {

 

            public MainPage() {

                InitializeComponent();

            }

 

            private void Button_Click_1(object sender, RoutedEventArgs e) {

                PrintDocument PD = new PrintDocument();

                PD.PrintPage += PD_PrintPage;

                PD.Print("Print Test");

            }

 

            void PD_PrintPage(object sender, PrintPageEventArgs e) {  

                Canvas OuterCanvas = new Canvas();

                /* a container for everything that will print */

                Border OuterBorder = new Border() {

                    BorderThickness = new Thickness(3),

                    BorderBrush = new SolidColorBrush(Colors.Red),

                    Margin = new Thickness(10)

                };   

 

                double Width = e.PrintableArea.Width - OuterBorder.Margin.Left - OuterBorder.Margin.Right;

                double Height = e.PrintableArea.Height - OuterBorder.Margin.Top - OuterBorder.Margin.Bottom;

                /* NOTE: We're trying to force landscape, so swop the width and height */

                OuterBorder.Width = Height;

                OuterBorder.Height = Width;

                /* on portrait, this line goes down (leave the printer settings, we're trying to force landscape) */

                Line Line = new Line() {

                    X1 = OuterBorder.Width / 2,

                    Y1 = 0,

                    X2 = OuterBorder.Width / 2,

                    Y2 = OuterBorder.Height,

                    Stroke = new SolidColorBrush(Colors.Blue),

                    StrokeThickness = 3

                };

                OuterBorder.Child = Line;

                OuterCanvas.Children.Add(OuterBorder);

 

                /* rotate 90 degrees, and move into place */

                var transformGroup = new TransformGroup();

                transformGroup.Children.Add(new RotateTransform() { Angle = 90 });

                transformGroup.Children.Add(new TranslateTransform() { X = e.PrintableArea.Width });

                OuterBorder.RenderTransform = transformGroup;

                e.PageVisual = OuterCanvas;

                e.HasMorePages = false;

            }

        }

    }

If you don't put the border inside of a canvas, it causes the page to appear cut off as if still printing portrait.


Tags:

Comments

Martin Lottering (not verified)

Thanks, it helped a lot. 

admin
Offline
Joined: 02/05/2009

No problem, thanks for leaving a comment :)

Martin Lottering (not verified)

 

 

May I add a small suggestion?
 
If you battle to get the landscape printing working properly because it cuts off:
 
Use a `canvas` container control, and **rotate** the control **inside of the canvas**.
 
 
After many hours of pure frustration, I finally decided to put the thing inside of a canvas. Voila!! No more cut off.
 
 
Have a look at the following SMALL test application to demonstrate. It is just a page with print button.
 
 
 
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    using System.Windows.Printing;
    using System.Windows.Shapes;
 
    namespace SilverlightApplication1 {
 
        public partial class MainPage : UserControl {
 
            public MainPage() {
 
                InitializeComponent();
 
            }
 
    
 
            private void Button_Click_1(object sender, RoutedEventArgs e) {
 
                PrintDocument PD = new PrintDocument();
 
                PD.PrintPage += PD_PrintPage;
 
                PD.Print("Print Test");
 
            }
 
    
 
            void PD_PrintPage(object sender, PrintPageEventArgs e) {  
 
                Canvas OuterCanvas = new Canvas();
 
 
                /* a container for everything that will print */
 
                Border OuterBorder = new Border() {
 
                    BorderThickness = new Thickness(3),
 
                    BorderBrush = new SolidColorBrush(Colors.Red),
 
                    Margin = new Thickness(10)
 
                };   
 
                double Width = e.PrintableArea.Width - OuterBorder.Margin.Left - OuterBorder.Margin.Right;
 
                double Height = e.PrintableArea.Height - OuterBorder.Margin.Top - OuterBorder.Margin.Bottom;
  
 
                /* NOTE: We're trying to force landscape, so swop the width and height */
 
                OuterBorder.Width = Height;
 
                OuterBorder.Height = Width;
 
 
                /* on portrait, this line goes down (leave the printer settings, we're trying to force landscape) */
 
                Line Line = new Line() {
 
                    X1 = OuterBorder.Width / 2,
 
                    Y1 = 0,
 
                    X2 = OuterBorder.Width / 2,
 
                    Y2 = OuterBorder.Height,
 
                    Stroke = new SolidColorBrush(Colors.Blue),
 
                    StrokeThickness = 3
 
                };
 
                OuterBorder.Child = Line;
 
                OuterCanvas.Children.Add(OuterBorder);
 
 
                /* rotate 90 degrees, and move into place */
 
                var transformGroup = new TransformGroup();
 
                transformGroup.Children.Add(new RotateTransform() { Angle = 90 });
 
                transformGroup.Children.Add(new TranslateTransform() { X = e.PrintableArea.Width });
 
                OuterBorder.RenderTransform = transformGroup;
 
                e.PageVisual = OuterCanvas;
 
                e.HasMorePages = false;
 
            }
        }
    }
 
 
If you don't put the border inside of a canvas, it causes the page to appear cut off as if still printing portrait.
Regards,
Martin

 

admin
Offline
Joined: 02/05/2009

Excellent suggestion. I don't use Silverlight much myself any more but since this is one of the most widely viewed pages on my site someone will get some use out of it. I'll paste it into the body of the post.