Printing in WPF

    General discussion

  • I've been playiing around trying to print a grid in Landscape sized to fit the page and with equal size columns.

    I created a user control with a datagrid and set the column widths to star.


    <UserControl x:Class=""
          d:DesignHeight="424" d:DesignWidth="1108">
            <Style TargetType="{x:Type TextBlock}">
                <Setter Property="Padding" Value="0,6"/>
                <Setter Property="FontWeight" Value="Bold"/>
            <Style TargetType="{x:Type DataGridColumnHeader}">
                <Setter Property="FontWeight" Value="Bold" />
                <Setter Property="Background" Value="#eeeeee" />
                <Setter Property="Padding" Value="4" />
                <Setter Property="Margin" Value="0" />
                <Setter Property="BorderThickness">
                        <Thickness Bottom="0" Left="1" Right="0" Top="1"/>
                <Setter Property="BorderBrush" Value="Black"/>
            <Style TargetType="{x:Type DataGridCell}">
                <Setter Property="BorderThickness">
                        <Thickness Bottom="0" Left="1" Right="0" Top="1"/>
                <Setter Property="BorderBrush" Value="Black"/>
        <Grid Margin="24,24">
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="auto"/>
            <StackPanel Orientation="Horizontal" Grid.ColumnSpan="3" HorizontalAlignment="Center">
                <TextBlock Text="Entry sheet for " />
                <TextBlock Name="EventName">Wed A Series</TextBlock>
                <TextBlock Name="EventDescription" Text=" - "/>
                <TextBlock Name="ClassName">Division 1</TextBlock>
            <StackPanel Grid.Row="1" Orientation="Horizontal">
                <TextBlock Text="Date: " />
                <TextBlock Name="StartDate">03 Aug 2010</TextBlock>
            <StackPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal">
                <TextBlock Text="Start: " />
                <TextBlock Name="StartTime">13.00</TextBlock>
            <StackPanel Grid.Row="1" Grid.Column="2" Orientation="Horizontal">
                <TextBlock Text="OOD: " />
                <TextBlock Name="OOD">Rothi</TextBlock>
            <StackPanel Grid.Row="2" Orientation="Horizontal">
                <TextBlock Text="Course: " />
                <Line Margin="5" VerticalAlignment="Bottom" X1="0" Y1="0" X2="200" Y2="0"  Stroke="Black" StrokeThickness="1"/>
            <StackPanel Grid.Row="2" Grid.Column="1" Orientation="Horizontal">
                <TextBlock Text="Actual Start: " />
                <Line Margin="5" VerticalAlignment="Bottom" X1="0" Y1="0" X2="80" Y2="0"  Stroke="Black" StrokeThickness="1"/>
            <StackPanel Grid.Row="2" Grid.Column="2" Orientation="Horizontal">
                <TextBlock Text="Weather: " />
                <Line Margin="5" VerticalAlignment="Bottom" X1="0" Y1="0" X2="200" Y2="0"  Stroke="Black" StrokeThickness="1"/>
            <DataGrid Grid.Row="3" Grid.ColumnSpan="3" Name="Entries"
                      CanUserReorderColumns="False" CanUserSortColumns="False"
                      BorderBrush="Black" GridLinesVisibility="None"
                      AutoGenerateColumns="False" IsReadOnly="True" RowHeight="40"
                      IsManipulationEnabled="False" HeadersVisibility="Column" >
                    <Thickness Bottom="1" Left="0" Right="1" Top="0"/>
                    <DataGridTextColumn Header="Boat name" Width="*"/>
                    <DataGridTextColumn Header="Class" Width="*"/>
                    <DataGridTextColumn Header="Sail No" Width="*"/>
                    <DataGridTextColumn Header="Lap 1" Width="*"/>
                    <DataGridTextColumn Header="Lap 2" Width="*"/>
                    <DataGridTextColumn Header="Lap 3" Width="*"/>
                    <DataGridTextColumn Header="Lap 4" Width="*"/>
                    <DataGridTextColumn Header="Lap 5" Width="*"/>
                    <DataGridTextColumn Header="Lap 6" Width="*"/>
                    <DataGridTextColumn Header="Lap 7" Width="*"/>

    And the code behind:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;

        /// <summary>
        /// Interaction logic for EntrySheets.xaml
        /// </summary>
        public partial class EntrySheet : UserControl
            public EntrySheet()
                string[] row = new string[] { "", "", "", "", "", "", "", "", "", "" };
                for (int i = 0; i < 15; i++)

    To print as simply as possible I tried the following:

                    PrintDialog pd = new PrintDialog();
                    pd.PrintTicket.PageOrientation = PageOrientation.Landscape;

                    if (pd.ShowDialog() == true)
                        EntrySheet es = new EntrySheet();
                        Size ps = new Size(pd.PrintableAreaWidth, pd.PrintableAreaHeight);
                        es.Arrange(new Rect(new Point(0, 0), ps));

                        XpsDocumentWriter xpwriter = PrintQueue.CreateXpsDocumentWriter(pd.PrintQueue);
                        xpwriter.Write(es, pd.PrintTicket);

    This prints in landscape but the columns dont size to fill the visible grid despite the grid filling the page width.

    I tried a somewhat more complex approach also:

                        PrintDialog pd = new PrintDialog();
                        pd.PrintTicket.PageOrientation = PageOrientation.Landscape;
                        Size ps = new Size(pd.PrintableAreaWidth, pd.PrintableAreaHeight);

                        EntrySheet p = new EntrySheet();

                        Frame f = new Frame();
                        f.Width = pd.PrintableAreaWidth;
                        f.HorizontalAlignment = HorizontalAlignment.Stretch;
                        FixedPage fp = new FixedPage();
                        fp.Width = pd.PrintableAreaWidth;
                        fp.Height = pd.PrintableAreaHeight;

                        PageContent pc = new PageContent();
                        IAddChild ac = pc as IAddChild;

                        pc.Arrange(new Rect(new Point(0, 0), ps));

                        FixedDocument fd = new FixedDocument();
                        fd.DocumentPaginator.PageSize = ps;

                        PrintPreview pv = new PrintPreview();
                        pv.Viewer.Document = fd;

    PrintPreview is a window containing a DocumentViewer to preview the document. Here everything looks good, equally sized colums using up the page width and showing in Landscape as desired.  But print the page and it comes out Portrait mode with the grid going off the page.

    • Edited by David Woakes Tuesday, August 03, 2010 7:17 PM Added a further example.
    Tuesday, August 03, 2010 6:27 PM

All replies

  • Hi David,

    I tested it in the Visual Studio 2008 with WPF Toolkit DataGrid and in the Visual Studio 2010 with WPF 4 DataGrid. The WPF Toolkit DataGrid can measure and arrange the corrent value to fit the width, and print out correctly. It seems the DataGrid in WPF can not render the correct size, I tested and found the RenderSize of the DataGrid is about (1122, 793), but the RenderSize of one column is about (20,25). It is wrong.

    I will send it internal for investigation. Meanwhile, you can also submit a feedback on Microsoft Connect site regarding this issue. I'll update here if I get any feedbacks.

    Thank you!

    For your second example which uses the DocumentViewer to print, I think you do not change the Orientation for the printer, please try to change it and print.


    Bob Bao

    MSDN Subscriber Support in Forum 

    If you have any feedback on our support, please contact

    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Wednesday, August 04, 2010 3:17 AM
  • Bob

    Thanks for looking this.

    Re Case 2, it's not reasonable having generated a Landscape orientated document to then have to select Landscape for the printer.  It should just happen. This is unworkable for a program used by other people because you have to tell people what they need to do at this stage.

    The FixedDocument has the orientation albeit in the pagesize which isn't perfect.

    In Word if you create a Landscape document and print it, it will come out in Landscape, you don't need to select Landscape.

    If it wont do it automatically then the DocumentViewer control should let you set something to indicate default orientation.  If the user changes that that is there funeral!

    I'll send in feedback on both.


    Wednesday, August 04, 2010 7:23 AM
  • Hi David,

    Yse, in the Word, we can set the page setup is for the PrintTicket. But in the FixedDocument.PageSize can not effect the PrintTicket. The PrintTicket value is independent with the FixedDocument.PageSize, we have to set the value for the printer. For your case, you should set the FixDocument.PrintTicket and the PageSize property, that can allow the printer to print the content in the specific direction.


    Bob Bao

    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Wednesday, August 04, 2010 1:02 PM