DEV Community

IronSoftware
IronSoftware

Posted on

XAML to PDF in .NET MAUI with C# (.NET Guide)

Our field service team needed offline reports generated from our .NET MAUI desktop app. The reports used XAML layouts—rich formatting, data grids, charts—that had to become PDFs for customer signatures.

IronPDF's MAUI extension converts ContentPages directly to PDF. Here's the implementation.

How Do I Convert MAUI Pages to PDF?

Install both IronPdf and IronPdf.Extensions.Maui packages:

Install-Package IronPdf
Install-Package IronPdf.Extensions.Maui
Enter fullscreen mode Exit fullscreen mode

Then use RenderContentPageToPdf:

using IronPdf;
using IronPdf.Extensions.Maui;
// Install via NuGet: Install-Package IronPdf.Extensions.Maui

var renderer = new [ChromePdfRenderer](https://ironpdf.com/blog/videos/how-to-render-webgl-sites-to-pdf-in-csharp-ironpdf/)();
var pdf = await renderer.RenderContentPageToPdf<MainPage, App>();
pdf.SaveAs("output.pdf");
Enter fullscreen mode Exit fullscreen mode

This renders the current MainPage as a PDF with all XAML layouts preserved.

Does This Work on Mobile?

No. IronPDF does not support iOS or Android. It works on:

  • Windows (desktop)
  • macOS (desktop)
  • Linux (desktop)

For mobile PDF generation, consider platform-specific libraries or server-side PDF creation with API calls.

Can I Render Pages Other Than MainPage?

Yes. Specify any ContentPage type:

var renderer = new ChromePdfRenderer();

// Render a custom report page
var pdf = await renderer.RenderContentPageToPdf<ReportPage, App>();
pdf.SaveAs("report.pdf");
Enter fullscreen mode Exit fullscreen mode

The page must be a valid ContentPage in your MAUI application.

How Do I Add Headers and Footers?

Configure RenderingOptions before rendering:

var renderer = new ChromePdfRenderer();

renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = "<h3 style='text-align:center'>Monthly Report</h3>"
};

renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='text-align:center'>Page {page} of {total-pages}</div>"
};

var pdf = await renderer.RenderContentPageToPdf<MainPage, App>();
pdf.SaveAs("with-headers.pdf");
Enter fullscreen mode Exit fullscreen mode

Headers and footers appear on every page.

Can I Style the PDF Output?

Yes. Apply CSS through RenderingOptions:

var renderer = new ChromePdfRenderer();

renderer.RenderingOptions.MarginTop = 50;
renderer.RenderingOptions.MarginBottom = 50;
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;

var pdf = await renderer.RenderContentPageToPdf<MainPage, App>();
pdf.SaveAs("styled.pdf");
Enter fullscreen mode Exit fullscreen mode

This sets margins and paper size for the output PDF.

Does Data Binding Work?

Not yet. RenderContentPageToPdf currently doesn't support XAML data binding. Static content renders correctly, but bound properties may not appear.

Workaround: populate controls programmatically before rendering:

public partial class ReportPage : ContentPage
{
    public ReportPage(ReportData data)
    {
        InitializeComponent();

        // Manually set values instead of binding
        TitleLabel.Text = data.Title;
        DataGrid.ItemsSource = data.Items;
    }
}

// Then render
var reportPage = new ReportPage(myData);
var pdf = await renderer.RenderContentPageToPdf<ReportPage, App>();
Enter fullscreen mode Exit fullscreen mode

How Do I Trigger PDF Generation from a Button?

Wire up a button click handler:

In MainPage.xaml:

<Button Text="Generate PDF" Clicked="OnGeneratePdfClicked" />
Enter fullscreen mode Exit fullscreen mode

In MainPage.xaml.cs:

private async void OnGeneratePdfClicked(object sender, EventArgs e)
{
    var renderer = new ChromePdfRenderer();
    var pdf = await renderer.RenderContentPageToPdf<MainPage, App>();

    var filePath = Path.Combine(FileSystem.AppDataDirectory, "report.pdf");
    pdf.SaveAs(filePath);

    await DisplayAlert("Success", $"PDF saved to {filePath}", "OK");
}
Enter fullscreen mode Exit fullscreen mode

Users click the button to generate PDFs on demand.

Can I Include Images from XAML?

Yes. Images embedded in XAML render in the PDF:

<Image Source="logo.png" HeightRequest="100" />
Enter fullscreen mode Exit fullscreen mode

Ensure images are included in your project as embedded resources or are accessible at runtime.

How Do I Handle Multi-Page Content?

Content that exceeds one page automatically flows to additional pages:

<ScrollView>
    <StackLayout>
        <Label Text="Page 1 content..." />
        <!-- Lots of content -->
        <Label Text="Page 2 content..." />
    </StackLayout>
</ScrollView>
Enter fullscreen mode Exit fullscreen mode

IronPDF paginates automatically based on content height and configured paper size.

What About Complex Layouts with Grids?

CollectionViews and data grids render correctly:

<CollectionView ItemsSource="{Binding Items}">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Label Grid.Column="0" Text="{Binding Name}" />
                <Label Grid.Column="1" Text="{Binding Value}" />
            </Grid>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>
Enter fullscreen mode Exit fullscreen mode

Note: As mentioned, data binding may not work. Populate ItemsSource programmatically before rendering.

Can I Generate PDFs Asynchronously?

Yes. RenderContentPageToPdf is async:

private async Task GenerateReportAsync()
{
    var renderer = new ChromePdfRenderer();

    // Runs without blocking UI
    var pdf = await renderer.RenderContentPageToPdf<ReportPage, App>();

    pdf.SaveAs("async-report.pdf");
}
Enter fullscreen mode Exit fullscreen mode

This keeps the UI responsive during PDF generation.

How Do I Save PDFs to User-Selected Locations?

Use file pickers:

private async void OnSavePdfClicked(object sender, EventArgs e)
{
    var renderer = new ChromePdfRenderer();
    var pdf = await renderer.RenderContentPageToPdf<MainPage, App>();

    var result = await FilePicker.PickAsync(new PickOptions
    {
        PickerTitle = "Save PDF"
    });

    if (result != null)
    {
        var stream = await result.OpenReadAsync();
        pdf.Stream.CopyTo(stream);
    }
}
Enter fullscreen mode Exit fullscreen mode

Users choose where to save the PDF.

What's the Performance Like?

Simple pages: 500-1000ms
Complex pages with images: 1-3 seconds
Pages with large data tables: 3-5 seconds

For better performance, generate PDFs on background threads:

await Task.Run(async () =>
{
    var renderer = new ChromePdfRenderer();
    var pdf = await renderer.RenderContentPageToPdf<ReportPage, App>();
    pdf.SaveAs("background-report.pdf");
});
Enter fullscreen mode Exit fullscreen mode

Can I Combine Multiple Pages into One PDF?

Render pages separately and merge:

var renderer = new ChromePdfRenderer();

var page1 = await renderer.RenderContentPageToPdf<CoverPage, App>();
var page2 = await renderer.RenderContentPageToPdf<DataPage, App>();
var page3 = await renderer.RenderContentPageToPdf<SummaryPage, App>();

var merged = PdfDocument.Merge(page1, page2, page3);
merged.SaveAs("complete-report.pdf");
Enter fullscreen mode Exit fullscreen mode

This creates multi-section reports from different XAML pages.

What About Printing the PDF?

After generation, trigger the OS print dialog:

var pdf = await renderer.RenderContentPageToPdf<MainPage, App>();

// Save temporarily
var tempPath = Path.Combine(FileSystem.CacheDirectory, "temp.pdf");
pdf.SaveAs(tempPath);

// Open in default PDF viewer for printing
await Launcher.OpenAsync(new OpenFileRequest
{
    File = new ReadOnlyFile(tempPath)
});
Enter fullscreen mode Exit fullscreen mode

Users can print from their default PDF application.

Does This Work with Custom Fonts?

Yes, if fonts are embedded in your MAUI app:

<Label Text="Custom Font Text" FontFamily="CustomFont" />
Enter fullscreen mode Exit fullscreen mode

Include fonts in MauiProgram.cs:

builder.ConfigureFonts(fonts =>
{
    fonts.AddFont("CustomFont.ttf", "CustomFont");
});
Enter fullscreen mode Exit fullscreen mode

Fonts render correctly in the PDF.

How Do I Test PDF Generation Locally?

Run your MAUI app on Windows or macOS and test the button:

  1. Click "Generate PDF"
  2. Check the output path in AppDataDirectory
  3. Open the PDF to verify layout

I use automated tests for batch PDF generation:

[Test]
public async Task GeneratesReportPdf()
{
    var renderer = new ChromePdfRenderer();
    var pdf = await renderer.RenderContentPageToPdf<ReportPage, App>();

    Assert.Greater(pdf.PageCount, 0);
    File.Exists("test-report.pdf");
}
Enter fullscreen mode Exit fullscreen mode

Written by Jacob Mellor, CTO at Iron Software. Jacob created IronPDF and leads a team of 50+ engineers building .NET document processing libraries.

Top comments (0)