如何在 WPF 中将整个 ScrollViewer 打印到 PDF 文件

How to print entire ScrollViewer to a PDF file in WPF

我有一个功能可以将我的布局打印到 PDF 文件(使用 PDFSharp 库)。

我的问题是我的 Grid 包含一个 ScrollViewer

问题是 ScrollViewer 显然不能在 PDF 文件中滚动。

有什么办法可以改变吗?

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>

您可以暂时增加 MainWindow.Height(或 Width,取决于您的 ScrollViewer 方向)以容纳整个 ScrollViewer 内容,等待新的 layout/render 通过,然后才打印成 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

我喜欢用这个扩展方法进行同步重绘操作:

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();
    }
}