Printing WPF UI Control on A4 Size Paper

This Post walks through the process of printing any WPF UI control on A4 paper while ensuring proper scaling and layout.

Printing WPF UI Control on A4 Size Paper

Getting Started

In Windows Presentation Foundation (WPF), printing a UI control directly to a physical page (like A4 size paper) is a common requirement for business applications whether it's for printing invoices, reports, or forms.

WPF does not provide out-of-the-box support for printing in specific paper sizes like A4. However, using the PrintDialog, Visual, XpsDocumentWriter and layout manipulation, we can render any UI control (like a Grid, Canvas, or UserControl) to the dimensions of A4 paper.

Before continuing to the printing part, let anderstanding what is A4 Size Paper and it's dimentions.

What is A4 Size Paper

A4 size paper is part of the ISO 216 standard used internationally (except in the U.S., Canada, and a few other countries). Here's what you need to know:

A4 Paper Dimensions:
  • A4 size in cm: is 21.0 cm × 29.7 cm
  • A4 size in inches: is 8.27 in × 11.69
  • A4 size in pixel: is (8.27*dpi × 11.69*dpi

DPI stands for Dots Per Inch, and it's a measure of a printer's resolution, how many tiny ink dots it can print in a single inch. 300 DPI is usually considered the minimum for professional-looking print.

Printing WPF UI Control

To Print a WPF UI control you can use PrintDialog from System.Windows.Controls namespace and XpsDocumentWriter from System.Windows.Xps which compes unser There are two scenarios that arise when printing a WPF UI control:

  1. Schenario-1: The UI is displayed on the screen and then printed.
  2. Schenario-2: The UI control is not displayed on the screen but is still printed.

Code examples for both scenarios are shared below. The following namespaces will be required:

 using System.Printing;  
 using System.Windows.Controls;  
 using System.Windows.Documents;  
 using System.Windows.Media;  
 using System.Windows.Xps;  
 using System.Windows.Xps.Packaging;  

Scenario-1: Using PrintDialog

A PrintDialog is a pre-configured dialog box in Windows-based applications that allows users to select a printer, choose which pages to print, and configure other print-related settings. It provides a standard and familiar interface for printing documents.

With Printer Dialogbox
 public void PrintElement(FrameworkElement elementToPrint)  
 {  
   // Create and show PrintDialog  
   PrintDialog printDialog = new PrintDialog();  
   // Optional: customize page settings (portrait, margins, etc.)  
   printDialog.PrintTicket.PageOrientation = PageOrientation.Portrait;  
   if (printDialog.ShowDialog() == true)  
   {  
     // Save original layout transform  
     var originalTransform = elementToPrint.LayoutTransform;  
     // Get the printable area size (in device-independent units, 1/96 inch)  
     double printableWidth = printDialog.PrintableAreaWidth;  
     double printableHeight = printDialog.PrintableAreaHeight;  
     // Calculate scale to fit element within printable area  
     double scaleX = printableWidth / elementToPrint.ActualWidth;  
     double scaleY = printableHeight / elementToPrint.ActualHeight;  
     double scale = Math.Min(scaleX, scaleY);  
     // Apply scaling  
     elementToPrint.LayoutTransform = new ScaleTransform(scale, scale);  
     // Re-measure and arrange the layout  
     Size printSize = new Size(elementToPrint.ActualWidth * scale, elementToPrint.ActualHeight * scale);  
     elementToPrint.Measure(printSize);  
     elementToPrint.Arrange(new Rect(printSize));  
     // Print the visual element  
     printDialog.PrintVisual(elementToPrint, "WPF UI Control Print");  
     // Restore original layout transform  
     elementToPrint.LayoutTransform = originalTransform;  
   }  
 }  

Without Printer Dialogbox
 public void PrintElement(FrameworkElement elementToPrint)  
 {  
      PrintDialog dlg = new PrintDialog();  
      var server = new PrintServer();  
      var queues = server.GetPrintQueues(new[] { EnumeratedPrintQueueTypes.Local, EnumeratedPrintQueueTypes.Connections });  
      var queue = queues.Where(t => t.FullName == "Microsoft Print to PDF").FirstOrDefault();  
      if (queue != null)  
           dlg.PrintQueue = queue;  
      else  
           throw new Exception("Printer not found");  
      dlg.PrintTicket.PageOrientation = PageOrientation.Portrait;  
       // Define A4 size in inches  
       const double A4WidthInInches = 8.27;  
       const double A4HeightInInches = 11.69;  
      int dpi = 96;  
      // Convert inches to WPF units (1 inch = 96 units)  
      double pageWidth = A4WidthInInches * dpi;  
      double pageHeight = A4HeightInInches * dpi;  
      dlg.PrintTicket.PageMediaSize = new PageMediaSize(pageWidth,pageHeight);  
      // Save original layout transform  
     var originalTransform = elementToPrint.LayoutTransform;  
      // Get the printable area size (in device-independent units, 1/96 inch)  
     double printableWidth = printDialog.PrintableAreaWidth;  
     double printableHeight = printDialog.PrintableAreaHeight;  
     // Calculate scale to fit element within printable area  
     double scaleX = printableWidth / elementToPrint.ActualWidth;  
     double scaleY = printableHeight / elementToPrint.ActualHeight;  
     double scale = Math.Min(scaleX, scaleY);  
      // Apply scaling  
     elementToPrint.LayoutTransform = new ScaleTransform(scale, scale);  
     // Re-measure and arrange the layout  
     Size printSize = new Size(elementToPrint.ActualWidth * scale, elementToPrint.ActualHeight * scale);  
     elementToPrint.Measure(printSize);  
     elementToPrint.Arrange(new Rect(printSize));  
     // Print the visual element  
     printDialog.PrintVisual(elementToPrint, "WPF UI Control Print");  
     // Restore original layout transform  
     elementToPrint.LayoutTransform = originalTransform;  
 }  

Note:-If you dont want to use the printer dialog box to set up printer paper then you have to manualy defin the height and width of A4 Paper like below

// Define A4 size in inches  
       const double A4WidthInInches = 8.27;  
       const double A4HeightInInches = 11.69;  
      int dpi = 96;  
      // Convert inches to WPF units (1 inch = 96 units)  
      double pageWidth = A4WidthInInches * dpi;  
      double pageHeight = A4HeightInInches * dpi;  
      dlg.PrintTicket.PageMediaSize = new PageMediaSize(pageWidth,pageHeight); 

Scenario-1: Using XpsDocumentWriter

XpsDocumentWriter is a class in the .NET Framework from in the System.Windows.Xps namespace that is used to write content to XPS documents or XML Paper Specification files. These are Microsoft's fixed-layout document format, similar to PDF. It allows you to output content like visuals, images, or entire documents to an .xps file or an XPS print job.

With Printer Dialogbox
 public void PrintElement(FrameworkElement elementToPrint)  
   {  
     if (elementToPrint == null)  
     {  
       MessageBox.Show("Nothing to print.");  
       return;  
     }  
     // Show the PrintDialog  
     PrintDialog printDialog = new PrintDialog();  
     if (printDialog.ShowDialog() == true)  
     {  
       // Save current size  
       Size originalSize = new Size(elementToPrint.ActualWidth, elementToPrint.ActualHeight);  
       // Measure and arrange the control for printing  
       elementToPrint.Measure(new Size(printDialog.PrintableAreaWidth, printDialog.PrintableAreaHeight));  
       elementToPrint.Arrange(new Rect(new Point(0, 0), elementToPrint.DesiredSize));  
       // Get the XpsDocumentWriter for the printer  
       XpsDocumentWriter xpsWriter = PrintQueue.CreateXpsDocumentWriter(printDialog.PrintQueue);  
       // Print the visual (element)  
       xpsWriter.Write(elementToPrint);  
       // Restore the original layout  
       elementToPrint.Measure(originalSize);  
       elementToPrint.Arrange(new Rect(new Point(0, 0), originalSize));  
     }  
   }  

Without Printer Dialogbox
  public void PrintElement(FrameworkElement elementToPrint)  
 {  
   // Define A4 size in inches  
   const double A4WidthInInches = 8.27;  
   const double A4HeightInInches = 11.69;  
   XpsDocumentWriter xpsWriter;  
   var server = new PrintServer();  
   var queues = server.GetPrintQueues(new[] { EnumeratedPrintQueueTypes.Local, EnumeratedPrintQueueTypes.Connections });  
   var queue = queues.Where(t => t.FullName == "Microsoft Print to PDF").FirstOrDefault();  
   if (queue != null)  
     xpsWriter = System.Printing.PrintQueue.CreateXpsDocumentWriter(queue);  
   else  
     throw new Exception("Printer not found");  
   int dpi = 96;  
   // Convert inches to WPF units (1 inch = 96 units)  
   double pageWidth = A4WidthInInches * dpi;  
   double pageHeight = A4HeightInInches * dpi;  
   // Set margins (in inches), then convert to WPF units  
   const double marginInInches = 0.5; // Half-inch margins  
   double margin = marginInInches * dpi;  
   // Calculate usable area after applying margins  
   double printableWidth = pageWidth - (2 * margin);  
   double printableHeight = pageHeight - (2 * margin);  
   // Measure and arrange the control for printing  
   elementToPrint.Measure(new Size(printableWidth, printableHeight));  
   elementToPrint.Arrange(new Rect(new Point(0, 0), elementToPrint.DesiredSize));  
   var printTicket = new PrintTicket  
   {  
     PageMediaSize = new PageMediaSize(PageMediaSizeName.ISOA4),  
     PageOrientation = PageOrientation.Portrait,  
     PageResolution = new PageResolution(dpi, dpi), // Set DPI here  
     PageMediaType = PageMediaType.Plain  
   };  
   // Print the visual (element)  
   xpsWriter.Write(elementToPrint, printTicket);  
 }  

Calling PrintElement Funcation
  private void Button_Click(object sender, RoutedEventArgs e)  
 {  
   this.PrintElement(this.gdprintdocument);//gdprintdocument is grid control  
 }  

Summary

Printing in WPF, especially to a specific format like A4, requires manual layout and scaling. With a little effort, however, you can create high-quality, professional prints of your UI elements using built-in WPF tools. I hope this was helpful to you.

Thanks

Kailash Chandra Behera

An IT professional with over 13 years of experience in the full software development life cycle for Windows, services, and web-based applications using Microsoft .NET technologies. Demonstrated expertise in delivering all phases of project development—from initiation to closure—while aligning with business objectives to drive process improvements, competitive advantage, and measurable bottom-line gains. Proven ability to work independently and manage multiple projects successfully. Committed to the efficient and effective development of projects in fast-paced, deadline-driven environments. Skills: Proficient in designing and developing applications using various Microsoft technologies. Total IT Experience: 13+ years

Previous Post Next Post

نموذج الاتصال