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:
- Schenario-1: The UI is displayed on the screen and then printed.
- 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.
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.
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