> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/core/get-started/samples/xaml2pdftest.md).

# Convert XAML to PDF - Xaml2Pdf - in C\#

Sample code for using Apryse SDK to dynamically generate PDF or XPS directly from a FlowDocument, XAML, or WPF. Samples provided in Python, C++, C#, Java, Node.js (JavaScript), PHP, Ruby, Go and VB. C

Sample code for using Apryse SDK to dynamically generate PDF or XPS directly from a FlowDocument, XAML, or WPF. Converting XAML/FlowDocument to PDF is not only easy, but is also very flexible in terms of how content is paginated and flowed into a fixed document such as PDF or XPS. Samples provided in Python, C++, C#, Java, Node.js (JavaScript), PHP, Ruby, Go and VB. Learn more about our [Server SDK](/core/get-started/get-started.md) and [PDF Conversion Library](/core/conversion/conversion.md).

{% tabs %}
{% tab title="C#" %}
{% code lineNumbers="true" %}

```csharp
//
// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
//
using System;
using System.IO;
using System.Windows;
using System.Windows.Documents; 
using System.Windows.Media; 
using System.Xml;
using System.Windows.Controls;
using System.Windows.Markup;

using pdftron;
using pdftron.Common;
using pdftron.SDF;
using pdftron.PDF;
using pdftron.Xaml;

namespace Xaml2PdfTestCS
{
    /// <summary>
    /// This sample shows how use pdftron.Xaml.Convert to convert .xaml files 
    /// into PDF documents with control over headers and footers, main body placement,
    /// and column widths.  Pagination is controlled by specifying the page size and 
    /// body size (margins) and all pages are appended to a PDFDoc which can then be
    /// further manipulated using the PDFNet API.
    /// 
    /// Three types of XAML objects are convertible using pdftron.Xaml.Convert:
    /// - FlowDocument's which describe content that is reflowable from page to page
    /// - FixedDocument's which describe content that has been placed on a fixed page
    /// - Blocks such as Canvas, RichTextBox, Section etc which can be wrapped or inserted 
    ///     directly into a FlowDocument
    ///     
    /// This sample has three example uses of pdftron.Xaml.Convert:
    /// - CreateXamlFlowDocumentFromCanvas() demonstrates how to read in a Canvas
    ///   described in a .xaml file and convert it to PDF.
    /// - CreateXamlTableAndConvert() demonstrates how to programmatically create
    ///   a FlowDocument with a table, and then convert it to PDF as a single column
    ///   document.
    /// - ConvertXamlFlowDocumentsFromFiles() demonstrates how to define functions to
    ///   create page headers and footers.
    ///   
    /// Limitations:
    /// Requires Microsoft .NET 3.5
    /// 
    /// There are many Xaml classes that cannot be added to FlowDocument or FixedDocuments and
    /// therefore this sample converter cannot convert Page, Window or Frame objects.
    /// </summary>
    class Program
    {
        private static pdftron.PDFNetLoader pdfNetLoader = pdftron.PDFNetLoader.Instance();
        static Program() {}
        
        // Relative path to the folder containing test files.
        const string inputPath = "../../TestFiles/";
        const string outputPath = "../../../../TestFiles/Output/";
        
        /// <summary>
        /// Entry point for the sample.
        /// </summary>
        /// <param name="args">command line arguments (ignored)</param>
        [STAThread]
        static void Main(string[] args)
        {
            PDFNet.Initialize(PDFTronLicense.Key);
            try
            {
                CreateXamlFlowDocumentFromCanvas();
                CreateXamlTableAndConvert();
                ConvertXamlFlowDocumentsFromFiles();
            }
            catch (PDFNetException e)
            {
                Console.WriteLine(e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            PDFNet.Terminate();
        }

        /// <summary>
        /// Demonstrate how to load a Xaml file containing a Canvas and convert
        /// it to PDF.
        /// </summary>
        static public void CreateXamlFlowDocumentFromCanvas()
        {
            // load the Xaml file containing the canvas
            string rawXamlText = "";
            using(StreamReader streamReader = File.OpenText(inputPath + "xamlshield.xaml"))
            {
                rawXamlText = streamReader.ReadToEnd();
            }
            StringReader stringReader = new StringReader(rawXamlText);
            XmlReader xmlReader = XmlReader.Create(stringReader);
            Canvas canvasImage = (Canvas)XamlReader.Load(xmlReader);

            // Now convert to PDF
            using (PDFDoc pdfdoc = new PDFDoc())
            {
                pdftron.Xaml.Convert.ToPdf(pdfdoc, canvasImage);
                string outputFileName = outputPath + "xamlshield.pdf";
                pdfdoc.Save(outputFileName, SDFDoc.SaveOptions.e_linearized);

                Console.WriteLine("Wrote " + outputFileName);
                Console.WriteLine("Done.");
            }
        }

        /// <summary>
        /// Demonstrate how to create a Xaml table and convert it to 
        /// PDF.  Also demonstrates how to use the ConverterOptions.NumColumns
        /// setting to draw the table across the page, rather than across
        /// the left column of a two column page.
        /// </summary>
        static public void CreateXamlTableAndConvert()
        {
            // from MSDN SDK Sample TableCsharpSample
            FlowDocument flowDoc = new FlowDocument();

            pdftron.Xaml.ConverterOptions options = new ConverterOptions();
            options.NumColumns = 1;

            // Create the Table...
            Table table1 = new Table();
            // ...and add it as a content element of the TextFlow.
            flowDoc.Blocks.Add(table1);
            // tf1.ContentStart.InsertTextElement(table1);

            // Set some global formatting properties for the table.
            table1.CellSpacing = 10;
            table1.Background = Brushes.White;

            // Create 6 columns and add them to the table's Columns collection.
            int numberOfColumns = 6;
            for (int x = 0; x < numberOfColumns; x++) table1.Columns.Add(new TableColumn());

            // Set alternating background colors for the middle colums.
            table1.Columns[1].Background =
                table1.Columns[3].Background =
                Brushes.LightSteelBlue;
            table1.Columns[2].Background =
                table1.Columns[4].Background =
                Brushes.Beige;

            // Create and add an empty TableRowGroup to hold the table's Rows.
            table1.RowGroups.Add(new TableRowGroup());

            // Add the first (title) row.
            table1.RowGroups[0].Rows.Add(new TableRow());

            // Alias the current working row for easy reference.
            TableRow currentRow = table1.RowGroups[0].Rows[0];

            // Global formatting for the title row.
            currentRow.Background = Brushes.Silver;
            currentRow.FontSize = 40;
            currentRow.FontWeight = System.Windows.FontWeights.Bold;

            // Add the header row with content, 
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run("2004 Sales Project"))));
            // and set the row to span all 6 columns.
            currentRow.Cells[0].ColumnSpan = 6;

            // Add the second (header) row.
            table1.RowGroups[0].Rows.Add(new TableRow());
            currentRow = table1.RowGroups[0].Rows[1];

            // Global formatting for the header row.
            currentRow.FontSize = 18;
            currentRow.FontWeight = FontWeights.Bold;

            // Add cells with content to the second row.
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Product"))));
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Quarter 1"))));
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Quarter 2"))));
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Quarter 3"))));
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Quarter 4"))));
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run("TOTAL"))));

            table1.RowGroups[0].Rows.Add(new TableRow());
            currentRow = table1.RowGroups[0].Rows[2];

            // Global formatting for the row.
            currentRow.FontSize = 12;
            currentRow.FontWeight = FontWeights.Normal;

            // Add cells with content to the third row.
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Widgets"))));
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run("$50,000"))));
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run("$55,000"))));
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run("$60,000"))));
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run("$65,000"))));
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run("$230,000"))));

            // Bold the first cell.
            currentRow.Cells[0].FontWeight = FontWeights.Bold;

            // Add the fourth row.
            table1.RowGroups[0].Rows.Add(new TableRow());
            currentRow = table1.RowGroups[0].Rows[3];

            // Global formatting for the row.
            currentRow.FontSize = 12;
            currentRow.FontWeight = FontWeights.Normal;

            // Add cells with content to the third row.
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Wickets"))));
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run("$100,000"))));
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run("$120,000"))));
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run("$160,000"))));
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run("$200,000"))));
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run("$580,000"))));

            // Bold the first cell.
            currentRow.Cells[0].FontWeight = FontWeights.Bold;

            table1.RowGroups[0].Rows.Add(new TableRow());
            currentRow = table1.RowGroups[0].Rows[4];

            // Global formatting for the footer row.
            currentRow.Background = Brushes.LightGray;
            currentRow.FontSize = 18;
            currentRow.FontWeight = System.Windows.FontWeights.Normal;

            // Add the header row with content, 
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Projected 2004 Revenue: $810,000"))));
            // and set the row to span all 6 columns.
            currentRow.Cells[0].ColumnSpan = 6;

            // The PDFDoc to put the converted .xaml document into
            using (PDFDoc pdfdoc = new PDFDoc())
            {
                pdftron.Xaml.Convert.ToPdf(pdfdoc, flowDoc, options );
                string outputFileName = outputPath + "CreateXamlTableAndConvert.pdf";
                pdfdoc.Save(outputFileName, SDFDoc.SaveOptions.e_linearized);

                Console.WriteLine("Wrote " + outputFileName);
                Console.WriteLine("Done.");
            }
        }

        /// <summary>
        /// Demonstrate how to convert Xaml files directly from .xaml to .pdf
        /// </summary>
        static public void ConvertXamlFlowDocumentsFromFiles()
        {
            string[] inputFileNames = new string[] {"BobWatson.xaml",
                                         "chocolate.xaml",
                                         "FlowDocumentFormats.xaml",
                                         "FlowDocumentSample1.xaml",
                                         "FlowDocumentSample2.xaml",
                                         "FlowDocumentSample3.xaml",
                                         "MarkusEgger.xaml",
                                         "MarkusEgger-withImageReference.xaml",
                                         "RichTextBox.xaml",
                                         "ThreeRectangles.xaml",
                                         "WPFNotepad-1.xaml"};

            foreach( string inputFileName in inputFileNames)
            {
                try
                {
                    // The PDFDoc to put the converted .xaml document into
                    using (PDFDoc pdfdoc = new PDFDoc())
                    {

                        ConverterOptions options = new ConverterOptions();
                        options.HeaderFunc = new ConverterOptions.DrawHeaderFooter(MyDrawHeader);
                        options.FooterFunc = new ConverterOptions.DrawHeaderFooter(MyDrawFooter);

                        pdftron.Xaml.Convert.ToPdf(pdfdoc, inputPath + inputFileName, options);
                        
                        // output the PDFDoc:
                        string outputFileName = inputFileName;
                        outputFileName = outputFileName.Remove(outputFileName.LastIndexOf('.')) + ".pdf";
                        outputFileName = outputPath + outputFileName;
                        pdfdoc.Save(outputFileName, SDFDoc.SaveOptions.e_linearized);

                        Console.WriteLine("Wrote " + outputFileName);
                        Console.WriteLine("Done.");
                    }
                }
                catch (PDFNetException e)
                {
                    Console.WriteLine(e.Message);
                    Console.WriteLine("For file " + inputFileName);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                    Console.WriteLine("For file " + inputFileName);
                }
            }
        }

        /// <summary>
        /// This variable hold the typeface resource used by the header and footer.
        /// Any resource that you use in the header and footer delegates must persist 
        /// until the document is serialized.
        /// </summary>
        static Typeface typeface = null;

        /// <summary>
        /// Example Header delegate for ConverterOptions, used in ConvertXamlFlowDocumentsFromFiles()
        /// </summary>
        static public void MyDrawHeader(DrawingContext context, pdftron.PDF.Rect bounds,
                                        pdftron.PDF.Rect bodyBounds, Size pageSize, int pageNumber)
        {
            // any resources that you use in the header and footer delegates must persist until the 
            // document is serialized
            if (typeface == null)
            {
                typeface = new Typeface("Comic Sans MS");
            }

            //12 point text for header page number
            FormattedText text = new FormattedText("Page " + (pageNumber + 1),
                System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight,
                typeface, 12, Brushes.Black);
            // the translation applied to the page put the origin at the top left corner of the 
            // body rectangle.  So negative y values move us out of the body into the top margin
            context.DrawText(text, new System.Windows.Point(0, -bounds.y2));
        }

        /// <summary>
        /// Example Footer delegate for ConverterOptions, used in ConvertXamlFlowDocumentsFromFiles()
        /// </summary>
        static public void MyDrawFooter(DrawingContext context, pdftron.PDF.Rect bounds,
                                        pdftron.PDF.Rect bodyBounds, Size pageSize, int pageNumber)
        {
            // any resources that you use in the header and footer delegates must persist until the 
            // document is serialized
            if (typeface == null)
            {
                typeface = new Typeface("Comic Sans MS");
            }

            //8 point text for footer in DarkGreen
            FormattedText text = new FormattedText("This is the footer for page " + (pageNumber + 1),
                System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight,
                typeface, 8, Brushes.DarkGreen);

            // The translation applied to the page puts the origin at the top left corner of the 
            // body rectangle, adjust.
            context.DrawText(text, new System.Windows.Point(0, bounds.y1 - bodyBounds.y1));
        }

    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/core/get-started/samples/xaml2pdftest.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
