C# : Is there a way to save a Window as PDF?

Viewed 935

I am using C# to generate a Window (scrollbar) with a lot of results: Window ResultsWindow = new Window();

At the bottom, there are two buttons, i.e. Cancel and Print. The first one does what it should. Nevertheless, the Print button should somehow convert the Window into a PDF File, or maybe one step inbetween where the user can save it afterwards.

    private void Print_click(object sender, RoutedEventArgs e)
    {   
        //add code to print the whole window??
        ResultsWindow.Close();            
    }

Does anyone of you have an idea how this could work?

Best regards

2 Answers

This isn't particularly pretty (or tested) but uses information from this answer.

This creates an XPS file of your window, and converts it to PDF

using System.IO;
using System.IO.Packaging;
using System.Windows;
using System.Windows.Xps;
using System.Windows.Xps.Packaging;

namespace WpfApp8
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            /*
             *  Convert WPF -> XPS -> PDF
             */
            MemoryStream lMemoryStream = new MemoryStream();
            Package package = Package.Open(lMemoryStream, FileMode.Create);
            XpsDocument doc = new XpsDocument(package);
            XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(doc);
            
            // This is your window
            writer.Write(this);

            doc.Close();
            package.Close();
            
            // Convert 
            MemoryStream outStream = new MemoryStream();
            PdfSharp.Xps.XpsConverter.Convert(lMemoryStream, outStream, false);

            // Write pdf file
            FileStream fileStream = new FileStream("C:\\test.pdf", FileMode.Create);
            outStream.CopyTo(fileStream);

            // Clean up
            outStream.Flush();
            outStream.Close();
            fileStream.Flush();
            fileStream.Close();
        }
    }
}

It uses the PdfSharp nuget package and the kenjiuno.PdfSharp.Xps package to add XPS support to PdfSharp

References

Asuming you are using WPF, here is how I accomplished something similar:

private void Button_Click(object sender, RoutedEventArgs e)
    {
        var wasMax = this.WindowState == WindowState.Maximized;
        UBlattWindow.WindowState = WindowState.Normal;
        var initHeight = UBlattWindow.ActualHeight;
        var initWidth = UBlattWindow.ActualWidth;
        UBlattWindow.Width = 955;
        UBlattWindow.Height = UBlattWindow.Height + (ScrollerContent.ActualHeight - Scroller.ActualHeight) + 20;

        Print(printGrid);
        UBlattWindow.Height = initHeight;
        UBlattWindow.Width = initWidth;
        if (wasMax)
        {
            UBlattWindow.WindowState = WindowState.Maximized;
        }
    }

    private void Print(Visual v)
    {

        System.Windows.FrameworkElement e = v as System.Windows.FrameworkElement;
        if (e == null)
            return;

        PrintDialog pd = new PrintDialog();
        if (pd.ShowDialog() == true)
        {
            PageMediaSize pageSize = null;

            pageSize = new PageMediaSize(PageMediaSizeName.ISOA4);

            pd.PrintTicket.PageMediaSize = pageSize;

            //store original scale
            Transform originalScale = e.LayoutTransform;
            //get selected printer capabilities
            System.Printing.PrintCapabilities capabilities = pd.PrintQueue.GetPrintCapabilities(pd.PrintTicket);

            //get scale of the print wrt to screen of WPF visual
            double scale = Math.Min(capabilities.PageImageableArea.ExtentWidth / e.ActualWidth, capabilities.PageImageableArea.ExtentHeight /
                           e.ActualHeight);

            //Transform the Visual to scale
            e.LayoutTransform = new ScaleTransform(scale, scale);

            //get the size of the printer page
            System.Windows.Size sz = new System.Windows.Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight);

            //update the layout of the visual to the printer page size.
            e.Measure(sz);
            e.Arrange(new System.Windows.Rect(new System.Windows.Point(capabilities.PageImageableArea.OriginWidth, capabilities.PageImageableArea.OriginHeight), sz));

            //now print the visual to printer to fit on the one page.
            pd.PrintVisual(v, "My Print");

            //apply the original transform.
            e.LayoutTransform = originalScale;
        }
    }

Note that I use the method Print to scale the Window, so it will fit a ISOA4 format. I also set my window to a fixed width and height before the print and reset it afterwards.

Related