.NET 7下WPF UI缩放适配打印时OxyPlot空白无法打印
OxyPlot在.NET 7 WPF中打印空白问题修复方案
复现步骤
- 克隆仓库:https://github.com/supershopping/OxyPlotPrintTest
- 运行应用程序
- 点击“Add Data”按钮
- 点击“Print”按钮,选择打印机并打印在letter尺寸纸张上
平台与版本
- 平台:WPF
- .NET版本:.NET 7
预期行为
目标是打印WPF UI中的ReportGrid或主窗口,打印代码用于将UI缩放适配到单张letter纸张,OxyPlot应随UI缩放并正常打印。
实际行为
打印后UI右侧的按钮正常显示,但OxyPlot区域为空白。相同打印代码在.NET Framework 4.8环境下可正常工作,推测是OxyPlot与.NET 7的兼容性问题,寻求修复方案或替代方法。
相关代码
XAML代码
<Window x:Class="OxyPlotPrintTest.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:OxyPlotPrintTest" xmlns:oxy="http://oxyplot.org/wpf" Title="MainWindow" Height="800" Width="1280" Name="Main"> <Grid Name="ReportGrid"> <Grid.ColumnDefinitions> <ColumnDefinition Width="5*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <oxy:PlotView x:Name="plot"/> <StackPanel Grid.Column="1"> <Button Content="Add Data" Click="Button_Click_1" Height="150"/> <Button Content="Print" Click="Button_Click" Height="150"/> </StackPanel> </Grid> </Window>
C#代码
public partial class MainWindow : Window { public PlotModel MyModel { get; private set; } public MainWindow() { MyModel = new PlotModel { Title = "Example 1" }; MyModel.Series.Add(new FunctionSeries(Math.Cos, 0, 10, 0.1, "cos(x)")); } private void Button_Click(object sender, RoutedEventArgs e) { Visual visual = ReportGrid as Visual; Print(visual); } private void Print(Visual v) { System.Windows.FrameworkElement e = v as System.Windows.FrameworkElement; if (e == null) return; PrintDialog pd = new PrintDialog(); pd.PrintTicket.PageOrientation = System.Printing.PageOrientation.Landscape; if (pd.ShowDialog() == true) { // 保存原始缩放比例 Transform originalScale = e.LayoutTransform; // 获取所选打印机的功能参数 System.Printing.PrintCapabilities capabilities = pd.PrintQueue.GetPrintCapabilities(pd.PrintTicket); // 计算打印相对于WPF视觉元素的缩放比例 double scale = Math.Min(capabilities.PageImageableArea.ExtentWidth / e.ActualWidth, capabilities.PageImageableArea.ExtentHeight / e.ActualHeight); // 应用缩放变换到视觉元素 e.LayoutTransform = new ScaleTransform(scale, scale); // 获取打印机页面尺寸 System.Windows.Size sz = new System.Windows.Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight); // 更新视觉元素布局以匹配打印机页面尺寸 e.Measure(sz); e.Arrange(new System.Windows.Rect(new System.Windows.Point(capabilities.PageImageableArea.OriginWidth, capabilities.PageImageableArea.OriginHeight), sz)); // 打印视觉元素以适配单页 pd.PrintVisual(v, "My Print"); // 恢复原始变换 e.LayoutTransform = originalScale; } } private void Button_Click_1(object sender, RoutedEventArgs e) { plot.Model = MyModel; } }
问题截图

修复方案
1. 强制OxyPlot打印前重绘
在调用pd.PrintVisual前,强制PlotView或PlotModel重绘,确保内容已渲染:
// 在pd.PrintVisual(v, "My Print");之前添加 plot.InvalidateVisual(); // 或者 plot.Model.InvalidatePlot(true);
2. 使用OxyPlot原生打印API
绕过WPF的PrintVisual,直接调用OxyPlot提供的打印方法,避免兼容性问题:
private void Button_Click(object sender, RoutedEventArgs e) { var printDialog = new PrintDialog(); printDialog.PrintTicket.PageOrientation = System.Printing.PageOrientation.Landscape; if (printDialog.ShowDialog() == true) { // 直接打印PlotModel plot.Model.Print(printDialog.PrintQueue, printDialog.PrintTicket); } }
3. 调整布局更新逻辑
应用缩放变换后,强制更新布局并等待渲染完成:
// 在e.Arrange之后添加 e.UpdateLayout(); // 临时等待渲染(仅作为应急方案) System.Threading.Thread.Sleep(100);
4. 升级OxyPlot版本
检查当前OxyPlot版本,升级到最新稳定版(如2.1.0及以上),新版本已修复部分.NET 7兼容性问题。
内容的提问来源于stack exchange,提问作者Owen Lee
相关产品推荐
相关产品推荐

