You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF中FlowDocument打印预览时LiveCharts2内容不显示的解决方法

解决WPF FlowDocument中LiveCharts2图表在打印预览不显示的问题

在WPF项目中,将LiveCharts2的CartesianChart放入FlowDocument的BlockUIContainer中时,打印预览里图表内容无法显示,以下是问题场景的相关代码:

问题代码

1. FlowDocument1.xaml

<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
              xmlns:lvc="clr-namespace:LiveChartsCore.SkiaSharpView.WPF;assembly=LiveChartsCore.SkiaSharpView.WPF" 
              xmlns:local="clr-namespace:Wpf.Start.Assets.Prints"
              ColumnWidth="400" FontSize="14">
   
    <Paragraph TextAlignment="Center" FontSize="16" FontWeight="Bold">
        <Run Text="{Binding Name}"></Run>
    </Paragraph>
    <BlockUIContainer>
        <Grid Background="#888">
            <lvc:CartesianChart Height="300" Series="{Binding Series1}" XAxes="{Binding XAxes1}" YAxes="{Binding YAxes1}" />
        </Grid>
    </BlockUIContainer>
</FlowDocument>

2. MainViewModel.cs

var printPre = new PrintPreView("Assets/Prints/FlowDocument1.xaml", DeviceInfo); printPre.ShowDialog();

3. PrintPreView.xaml

<Window x:Class="Wpf.Start.Views.PrintPreView"         
        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:lvc="clr-namespace:LiveChartsCore.SkiaSharpView.WPF;assembly=LiveChartsCore.SkiaSharpView.WPF"           
        xmlns:local="clr-namespace:Wpf.Start.Views"         
        mc:Ignorable="d"         
        Title="" Height="450" Width="800">     
    <Grid>         
        <DocumentViewer Name="viewer" />     
    </Grid> 
</Window>

4. PrintPreView.xaml.cs

public PrintPreView(string fileName, DeviceInfo data)
{
    InitializeComponent();
    var flowDocument = (FlowDocument)Application.LoadComponent(new Uri(fileName, UriKind.RelativeOrAbsolute));
    flowDocument.DataContext = data;
    Dispatcher.BeginInvoke(() =>
    {
        MemoryStream ms = new MemoryStream();
        Package package = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);
        Uri DocumentUri = new Uri("pack://InMemoryDocument.xps");
        PackageStore.RemovePackage(DocumentUri);
        PackageStore.AddPackage(DocumentUri, package);
        XpsDocument xpsDocument = new XpsDocument(package, CompressionOption.Fast, DocumentUri.AbsoluteUri);

        XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(xpsDocument);
        var paginator = (flowDocument as IDocumentPaginatorSource).DocumentPaginator;
        writer.Write(paginator);
    
        viewer.Document = xpsDocument.GetFixedDocumentSequence();
    
        xpsDocument.Close();
    }, DispatcherPriority.ApplicationIdle);
}

解决方案

问题根源在于:FlowDocument转XPS时,BlockUIContainer中的CartesianChart控件还未完成布局渲染就被写入XPS,导致图表内容无法被捕获。可以通过以下步骤修复:

1. 强制控件完成布局和渲染

在生成XPS前,需要确保FlowDocument中的所有UI控件都完成布局和渲染。可以将FlowDocument临时加载到一个隐藏的FlowDocumentReader中,触发布局更新。

2. 修改PrintPreView.xaml.cs代码

更新构造函数逻辑,先让控件完成渲染再生成XPS:

public PrintPreView(string fileName, DeviceInfo data)
{
    InitializeComponent();
    var flowDocument = (FlowDocument)Application.LoadComponent(new Uri(fileName, UriKind.RelativeOrAbsolute));
    flowDocument.DataContext = data;

    // 创建临时FlowDocumentReader触发控件布局
    var tempReader = new FlowDocumentReader
    {
        Document = flowDocument,
        Visibility = Visibility.Collapsed,
        Width = flowDocument.PageWidth,
        Height = flowDocument.PageHeight
    };

    // 添加到窗口可视化树
    (Content as Grid).Children.Add(tempReader);

    Dispatcher.BeginInvoke(async () =>
    {
        // 强制更新布局
        tempReader.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
        tempReader.Arrange(new Rect(tempReader.DesiredSize));
        tempReader.UpdateLayout();

        // 短暂延迟确保LiveCharts2完成绘制
        await Task.Delay(100);

        MemoryStream ms = new MemoryStream();
        Package package = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);
        Uri DocumentUri = new Uri("pack://InMemoryDocument.xps");
        PackageStore.RemovePackage(DocumentUri);
        PackageStore.AddPackage(DocumentUri, package);
        XpsDocument xpsDocument = new XpsDocument(package, CompressionOption.Fast, DocumentUri.AbsoluteUri);

        XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(xpsDocument);
        var paginator = (flowDocument as IDocumentPaginatorSource).DocumentPaginator;
        writer.Write(paginator);
    
        viewer.Document = xpsDocument.GetFixedDocumentSequence();
    
        xpsDocument.Close();

        // 移除临时控件
        (Content as Grid).Children.Remove(tempReader);
    }, DispatcherPriority.Render);
}

3. 额外优化:手动触发图表刷新

如果上述方法仍不生效,可在设置DataContext后手动找到CartesianChart并强制刷新:

// 在flowDocument.DataContext = data;之后添加
var blockContainer = flowDocument.Blocks.OfType<BlockUIContainer>().FirstOrDefault();
if (blockContainer?.Child is Grid grid)
{
    var chart = grid.Children.OfType<CartesianChart>().FirstOrDefault();
    chart?.InvalidateVisual();
}

内容的提问来源于stack exchange,提问作者omitoufa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 03:01:07