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

WPF中ScrollViewer滚动后打印完整POS小票的方法

WPF POS小票打印滚动后仅打印可见区域的解决办法

问题根因

WPF的ScrollViewer会对超出可视范围的内容做虚拟化或暂不渲染处理,默认打印方式(直接打印ScrollViewer的Visual)只会捕获当前显示的可见部分,所以滚动后打印就只出可见区域。

解决思路

要么临时让ScrollViewer展开显示全部内容,打印后恢复状态;要么直接针对内容容器进行打印,绕开ScrollViewer的可视限制。

具体实现方案

方案1:临时展开ScrollViewer打印

先保存ScrollViewer的滚动位置和尺寸,临时把它的高度设为内容的实际高度,让所有内容都渲染出来,打印完成后再恢复原样。

修改后的C#打印代码

private void PrintButton_Click(object sender, RoutedEventArgs e)
{
    // 替换成你自己的ScrollViewer和内容容器名称
    var scrollViewer = printScrollViewer;
    var contentContainer = printContent;

    // 保存原始状态
    var originalScrollPos = scrollViewer.VerticalOffset;
    var originalScrollHeight = scrollViewer.Height;

    try
    {
        // 临时展开ScrollViewer,显示全部内容
        scrollViewer.Height = contentContainer.ActualHeight;
        scrollViewer.UpdateLayout(); // 强制刷新布局,确保内容全渲染

        var printDialog = new PrintDialog();
        if (printDialog.ShowDialog() == true)
        {
            // 打印内容容器,而非ScrollViewer本身
            printDialog.PrintVisual(contentContainer, "POS小票");
        }
    }
    finally
    {
        // 恢复ScrollViewer的原始状态
        scrollViewer.Height = originalScrollHeight;
        scrollViewer.ScrollToVerticalOffset(originalScrollPos);
        scrollViewer.UpdateLayout();
    }
}

方案2:用FlowDocument打印(更适合动态内容)

如果小票内容是动态生成的,可以把内容转成FlowDocument,用文档分页器打印,完全不受ScrollViewer影响。

示例代码

private void PrintButton_Click(object sender, RoutedEventArgs e)
{
    var printDialog = new PrintDialog();
    if (printDialog.ShowDialog() != true) return;

    // 创建空的FlowDocument
    var printDoc = new FlowDocument();
    var contentPanel = printContent as StackPanel;

    // 把小票内容逐控件转成FlowDocument的元素
    foreach (var child in contentPanel.Children)
    {
        if (child is TextBlock tb)
        {
            var para = new Paragraph(new Run(tb.Text));
            para.FontFamily = tb.FontFamily;
            para.FontSize = tb.FontSize;
            para.Margin = tb.Margin;
            printDoc.Blocks.Add(para);
        }
        // 其他控件(如Border、Image)可按需转换
    }

    // 适配小票打印尺寸
    printDoc.PageWidth = printDialog.PrintableAreaWidth;
    printDoc.PageHeight = printDialog.PrintableAreaHeight;

    printDialog.PrintDocument(((IDocumentPaginatorSource)printDoc).DocumentPaginator, "POS小票");
}

XAML配置注意

确保内容容器(比如StackPanel)不设置固定高度,让它随内容自动扩展:

<ScrollViewer x:Name="printScrollViewer" VerticalScrollBarVisibility="Auto">
    <StackPanel x:Name="printContent" Width="280">
        <!-- 这里放小票的具体内容:订单号、商品列表、总计等 -->
    </StackPanel>
</ScrollViewer>

核心提醒

  • 绝对不要直接打印ScrollViewer,要打印它内部的内容容器,避免只捕获可见区域。
  • 打印前必须调用UpdateLayout(),强制WPF渲染全部内容。
  • 打印后一定要恢复ScrollViewer的原始状态,不影响用户后续操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 16:20:08