tenminmail
tenminmail

Reputation: 83

How to print entire ScrollViewer to a PDF file in WPF

I have a function that prints my layout to a PDF file (using PDFSharp library).

My problem is that my Grid includes a ScrollViewer.

The Problem is that the ScrollViewer obviously is not scrollable in the PDF file.

Is there a way i can change that ?

Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
dlg.FileName = "NHF Tool";
dlg.DefaultExt = ".pdf";
dlg.Filter = "PDF (.pdf)|*.pdf";

Nullable<bool> result = dlg.ShowDialog();

try
{
    if (result == true)
    {
        MemoryStream lMemoryStream = new MemoryStream();
        Package package = Package.Open(lMemoryStream, FileMode.Create);
        XpsDocument doc = new XpsDocument(package);
        XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(doc);
        writer.Write(MainCanvas);
        doc.Close();
        package.Close();
        var pdfXpsDoc = PdfSharp.Xps.XpsModel.XpsDocument.Open(lMemoryStream);
        PdfSharp.Xps.XpsConverter.Convert(pdfXpsDoc, dlg.FileName, 0);
    }
}
catch (System.IO.IOException)
{
    MessageBox.Show("TEMP");
}
<Window x:Class="NHF_Tool.MainWindow" 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:my="clr-namespace:NHF_Tool"
  Title="Test" Height="800" Width="1525">

    <Grid Background="Gainsboro">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <GroupBox Grid.Row="0" Header="Test1" Margin="10">
            <Grid>
                <Button Content="Sample content" Margin="20"/>
            </Grid>
        </GroupBox>

        <GroupBox Grid.Row="1" Header="Test2" Margin="10">
            <ScrollViewer x:Name="ScrollViewer">
                <StackPanel Orientation="Vertical">
                    <Rectangle Fill="LightYellow" Height="300" Margin="20"/>
                    <TextBox HorizontalAlignment="Center" Grid.Row="1" Text="TextBox"/>
                </StackPanel>
            </ScrollViewer>
        </GroupBox>
    </Grid>
</Window>

Upvotes: 1

Views: 1135

Answers (1)

Corentin Pane
Corentin Pane

Reputation: 4943

You can temporarily increase your MainWindow.Height (or Width, depending on your ScrollViewer orientation) to accomodate the whole ScrollViewer content, wait for a new layout/render pass and only then print it to PDF.

MainWindow window = this;
double oldHeight = window.Height; // saving regular Height for rollback
window.Height = 5000; // large enough temporary increase

window.SynchronouslyRedraw();

PrintToPdf(); // the method you already have
window.Height = oldHeight; // undo temporary increase

I like to use this extension method for synchronous redrawing operations:

public static class UIElementExtensions {
    /// <summary>
    /// Synchronously redraws this <see cref="UIElement"/>. Only works if in a <see cref="Window"/> visual tree.
    /// </summary>
    public static void SynchronouslyRedraw(this UIElement uiElement) {
        uiElement.InvalidateVisual();
        Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => { })).Wait();
        Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() => { })).Wait();
    }
}

Upvotes: 1

Related Questions