【问题标题】:FixedPage XPS/PDF content in won't fill the pageFixedPage XPS/PDF 内容不会填满页面
【发布时间】:2021-12-03 02:00:06
【问题描述】:

我已经尝试了几个小时,现在很不情愿地寻求帮助。

我有一个带有支持视图模型的 WPF 自定义控件,我想将它打印到 PDF(通过 XPS)。最终,这些控件将有多个页面。

根据 SO 和 MSDN 论坛上的几个示例,我编写了将创建包含控件的 PDF 文件的代码,但内容的大小不正确。

    var controlViewModelsToPrint = new InfoControlViewModel[] { ViewModel };

    // Assume 8.5"x11" size for now, get from print dialog later
    var xpsDPI = 96;
    var pageWidth = 8.5 * xpsDPI;
    var pageHeight = 11 * xpsDPI;

    var pageSize = new Size(pageWidth, pageHeight);

    // Document hierarchy: FixedDocument > PageContent > FixedPage > UIElement/Control

    var fixedDoc = new FixedDocument();

    foreach (var controlViewModel in controlViewModelsToPrint)
    {
        var pageContent = new PageContent();
        var fixedPage = new FixedPage();

        // The control to be printed is never displayed on screen so measure and arrage it.
        var controlView = new InfoControl(controlViewModel);

        controlView.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
        // I've read that using either this call to the dispatcher or an UpdateLayout would help - it doesn't.
        //Application.Current.Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle);
        controlView.Arrange(new Rect(controlView.DesiredSize));

        // Add the control/page/content through the document hierarchy
        fixedPage.Children.Add(controlView);
        ((IAddChild)pageContent).AddChild(fixedPage);

        // Set gage dimensions
        fixedPage.Width = pageSize.Width;
        fixedPage.Height = pageSize.Height;

        // Running Measure/Arrage on the fixed page does not alter the result.
        fixedPage.Measure(pageSize);
        fixedPage.Arrange(new Rect(fixedPage.DesiredSize));
        fixedPage.UpdateLayout();

        fixedDoc.Pages.Add(pageContent);
    }

    PrintFixedDocument(fixedDoc);

生成的 PDF: 我期待内容填满页面,如果它显示在 WPF 窗口中会不会:

我尝试了所有我能想到的测量、排列、更新布局调用的组合,但没有成功。

我也尝试了不同的 XPS 转 PDF 解决方案(PDFSharp 和 Print FixedDocument/XPS to PDF without showing file save dialog),但均未成功。

我在 GitHub 上有一个最小的工作示例:https://github.com/AndyStagg/PDFPrintingDemo

重新激活资源:

Convert WPF (XAML) Control to XPS Document

How to calculate FixedPage dimensions

Why do I have have to use UIElement.UpdateLayout?

编辑: 我尝试了更多的东西:

在固定页面上设置水平和垂直对齐方式

fixedPage.HorizontalAlignment = HorizontalAlignment.Stretch;
fixedPage.VerticalAlignment = VerticalAlignment.Stretch;

在控件上设置水平和垂直(常规和内容)对齐方式

controlView.HorizontalContentAlignment = HorizontalAlignment.Stretch;
controlView.VerticalContentAlignment = VerticalAlignment.Stretch;

controlView.HorizontalAlignment = HorizontalAlignment.Stretch;
controlView.VerticalAlignment = VerticalAlignment.Stretch;

controlView.DesiredSize 是 155x215,所以我尝试在 Arrage 调用中指定 pageSize

controlView.Arrange(new Rect(pageSize));

这导致controlView 对象具有正确的ActualHeightActualWidth,但生成的PDF 没有改变。

我已尝试将 pageSize 发送到 Measure 呼叫

controlView.Measure(pageSize);

运气不好。

最后但同样重要的是,我尝试在控件上设置宽度和高度

controlView.Width = pageSize.Width;
controlView.Height = pageSize.Height;

再次,没有运气。

我还尝试将 controlView 作为子级放置在边框、视图框和网格中

var border = new Border();
var controlView = new InfoControl(control);
border.Child = controlView;

border.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
border.Arrange(new Rect(border.DesiredSize));

// Add the control/page/content through the document hierarchy
fixedPage.Children.Add(border);

以及尝试在子级 (controlView) 上调用 Measure & Arrange 调用

var grid = new Grid();
var controlView = new InfoControl(control);

grid.Children.Add(controlView);

controlView.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
controlView.Arrange(new Rect(controlView.DesiredSize));

// Add the control/page/content through the document hierarchy
fixedPage.Children.Add(grid);

在这一点上我完全被难住了。

【问题讨论】:

    标签: c# pdf wpf-controls xpsdocument


    【解决方案1】:

    在尝试了几乎所有我能想到的创建文档和固定页面的逻辑之后,我转向UserControl 本身,之后,修复起来非常容易。

    我在UserControl 上使用了MeasuredOverride 方法来查看父级是否为FixedPage,如果是,则返回基于固定页面宽度和高度的大小,否则返回基本逻辑。这使得该控件仍可在 UI 中用于预览等。

    它确实不漂亮,但它确实有效。我确信它会有一些陷阱,但至少我可以继续弄清楚那些可能是什么。

    protected override Size MeasureOverride(Size constraint)
    {
        if (this.Parent is FixedPage fixedPage)
        {
            return new Size(fixedPage.Width, fixedPage.Height);
        }
    
        return base.MeasureOverride(constraint);
    }
    

    GitHub 存储库已更新,供日后查看完整解决方案的人使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-08
      • 1970-01-01
      • 2022-12-05
      • 2014-04-21
      • 1970-01-01
      • 2011-09-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多