FixedPage XPS/PDF 中的内容不会填满页面
FixedPage XPS/PDF content in won't fill the page
我已经尝试了几个小时,现在不情愿地寻求帮助。
我有一个带有支持视图模型的 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 window 中会是这样吗:
我已经尝试了所有我能想到的测量、安排、更新布局调用的组合,但都没有成功。
我也尝试过不同的 XPS 到 PDF 解决方案(PDFSharp 和 )但没有成功。
我在 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
对象具有正确的 ActualHeight
和 ActualWidth
,但生成的 PDF 没有变化。
我已经尝试将 pageSize
发送到 Measure 调用
controlView.Measure(pageSize);
运气不好。
最后但同样重要的是,我尝试在控件上设置宽度和高度
controlView.Width = pageSize.Width;
controlView.Height = pageSize.Height;
又一次,运气不好。
我也试过将 controlView
作为子对象放置在 Border、ViewBox 和 Grid
中
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);
此时我完全被难住了。
在尝试了几乎所有我能想到的创建文档和固定页面的逻辑之后,我转向 UserControl
本身,之后,修复起来出奇地容易。
我在 UserControl
上使用了 MeasuredOverride
方法来查看父级是否是 FixedPage
,如果是,return 基于固定的大小页面宽度和高度,否则 return 基本逻辑。这允许控件仍然在 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 存储库已更新,供将来查看完整解决方案的人使用。
我已经尝试了几个小时,现在不情愿地寻求帮助。
我有一个带有支持视图模型的 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:
我已经尝试了所有我能想到的测量、安排、更新布局调用的组合,但都没有成功。
我也尝试过不同的 XPS 到 PDF 解决方案(PDFSharp 和
我在 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
对象具有正确的 ActualHeight
和 ActualWidth
,但生成的 PDF 没有变化。
我已经尝试将 pageSize
发送到 Measure 调用
controlView.Measure(pageSize);
运气不好。
最后但同样重要的是,我尝试在控件上设置宽度和高度
controlView.Width = pageSize.Width;
controlView.Height = pageSize.Height;
又一次,运气不好。
我也试过将 controlView
作为子对象放置在 Border、ViewBox 和 Grid
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);
此时我完全被难住了。
在尝试了几乎所有我能想到的创建文档和固定页面的逻辑之后,我转向 UserControl
本身,之后,修复起来出奇地容易。
我在 UserControl
上使用了 MeasuredOverride
方法来查看父级是否是 FixedPage
,如果是,return 基于固定的大小页面宽度和高度,否则 return 基本逻辑。这允许控件仍然在 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 存储库已更新,供将来查看完整解决方案的人使用。