【问题标题】:C# WPF Printing job is removed when changing one line of code更改一行代码时删除 C# WPF 打印作业
【发布时间】:2016-03-07 17:04:36
【问题描述】:

我在尝试打印存储在 .xaml 文件中的 FlowDocument 时发现了一个奇怪的行为。让我向您展示这是如何工作的。我们有一个类似 ViewModel 的简单类:

public class FooViewModel
{
    public FlowDocument Fd { get; set; }

    public FooViewModel()
    {
        this.Fd = Application.LoadComponent(new Uri("/someassembly;component/somepath.xaml", UriKind.Relative)) as FlowDocument;
    }

    public void Print()
    {
        PrintDialog pd new PrintDialog();
        pd.PrintQueue = new PrintQueue(new LocalPrintServer(), "Canon MP280 series");

        FlowDocument document = this.Fd;
        document.DataContext = new LabelTicket(); //stores data for printing
        DocumentPaginator dp = ((IDocumentPaginatorSource)document).DocumentPaginator;
        pd.PrintDocument(dp, "someTitle");
    }
} 

此代码有效,打印作业已启动,物理打印机正在执行它的工作。但是当我们将Print()方法中的一行改成:

FlowDocument document = Application.LoadComponent(new Uri("/someassembly;component/somepath.xaml", UriKind.Relative)) as FlowDocument;

奇怪的事情开始发生。将组件加载延迟到实际打印会使打印变得不可能。打印作业出现在此特定打印机的 Windows 打印队列中,但几乎立即消失。打开打印的 Windows 事件跟踪显示:“打印处理器返回的 Win32 错误代码:63 (0x3f)。”将打印机更改为任何其他物理打印机都会产生相同的效果。

另一方面,将打印机更改为任何非物理打印机(如“Microsoft XPS Document Writer”)可以毫无问题地执行此打印。

我也尝试从 ResourceDictionary 加载 FlowDocument,但效果相同。谁能给我一个提示如何解决这个问题?

【问题讨论】:

  • Fd 绑定到 UI 了吗?

标签: c# wpf printing flowdocument


【解决方案1】:

不太明显的答案可能是您需要“显示”FlowDocument,以便它知道如何以某种方式呈现。使用像 XPS Doc Writer 这样的虚拟打印机,它可能知道如何正确渲染FlowDocument。在没有安装 XPS 驱动程序的打印机上,它可能不知道如何正确渲染。

您最好的选择可能是在将 FlowDocument 发送到打印机之前“静默”渲染它。此外,这可能不是纯 MVVM 视图模型,因为您的视图模型可能不应该引用 FlowDocument 甚至 PrintDialog

无论如何,你可以尝试做这样的事情来静默渲染:

public void Print()
{
    PrintDialog pd = new PrintDialog();
    if(pd.ShowDialog() == true) //allow user to pick printer and preferences if they choose to do so
    {

        FlowDocument document = Application.LoadComponent(new Uri("/someassembly;component/somepath.xaml", UriKind.Relative)) as FlowDocument;

        document.DataContext = new LabelTicket(); //stores data for printing

        Grid g = new Grid();
        ContentPresenter cp = new ContentPresenter();
        cp.Content = document;
        g.Children.Add(cp);
        var _printableAreaSize = new Size(pd.PrintableAreaWidth, pd.PrintableAreaHeight);
        g.Measure(_printableAreaSize);
        g.Arrange(new Rect(new Point(), _printableAreaSize));
        g.UpdateLayout();

        DocumentPaginator dp = ((IDocumentPaginatorSource)document).DocumentPaginator;

        pd.PrintDocument(dp, "someTitle");
    }
}

当您逐步执行 Measure/Arrange/UpdateLayout 调用时,您应该会看到 Grids 的高度/宽度发生了变化,因为它正在渲染而不实际显示。

【讨论】:

  • 如果您不想显示打印对话框,那么您应该使用LocalPrintServer.GetDefaultPrintQueue() 或其他可以为您提供可以打印的尺寸/尺寸的东西,这样您就可以在创建之前指定正确的尺寸分页器。
  • 出于设计和调试目的,我使用 VM 作为视图的绑定源。但是在进行测试时,我已经从视图中删除了 FlowDocument。现在,在创建视图(作为静态资源)期间正在初始化 VM,然后 FlowDocument 工作,但是当我将它移动到应用程序的任何不同部分时,它基本上已经死了。当然,您也是对的,应该显示它以使其工作,但是为什么构造函数使这成为可能呢?目前,我重新设计了 FlowDocument,使其只使用表格和段落,现在它可以在任何地方工作而无需显示。
猜你喜欢
  • 1970-01-01
  • 2023-04-10
  • 2012-10-30
  • 1970-01-01
  • 1970-01-01
  • 2012-06-23
  • 2015-03-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多