【问题标题】:WPF printing/xps issueWPF 打印/xps 问题
【发布时间】:2012-12-05 11:40:37
【问题描述】:

我编写了以下代码块,可以在发送到物理打印机时完美打印我的 ListBox,但是当尝试将其发送到 XPS 打印机驱动程序或使用 XpsDocumentWriter 类时(我假设它们在hood) 我收到以下异常:

System.ArgumentException 未被用户代码处理 Message=Width 和 Height 必须为非负数。 来源=ReachFramework 堆栈跟踪: 在 System.Windows.Xps.Serialization.VisualSerializer.WriteTileBrush(字符串元素,TileBrush 画笔,矩形边界)

该异常显然表明一个项目没有正确的宽度/高度,但是我在将代码发送到不同的打印机(物理和 XPS 驱动程序)时调试了代码,但我无法找到任何差异。

以下是我如何创建要发送到打印机的视觉效果:

private ScrollViewer GeneratePrintableView()
    {
        ScrollViewer scrollView = new ScrollViewer();

        Grid grid = new Grid { Background = Brushes.White, Width = this.myListBox.ActualWidth, Height = this.myListBox.ActualHeight };

        grid.RowDefinitions.Add(new RowDefinition());
        grid.RowDefinitions[0].Height = new GridLength(0, GridUnitType.Auto);
        grid.RowDefinitions.Add(new RowDefinition());
        grid.RowDefinitions[1].Height = new GridLength(0, GridUnitType.Auto);

        // Add the title and icon to the top
        VisualBrush titleClone = new VisualBrush(this.TitleBar);
        var titleRectangle = new Rectangle { Fill = titleClone, Width = this.TitleBar.ActualWidth, Height = this.TitleBar.ActualHeight };
        grid.Children.Add(titleRectangle);
        Grid.SetRow(titleRectangle, 0);

        this.myListBox.Width = this.myListBox.ActualWidth;
        this.myListBox.Height = this.myListBox.ActualHeight;

        VisualBrush clone = new VisualBrush(this.myListBox) { Stretch = Stretch.None, AutoLayoutContent = true };
        var rectangle = new Rectangle { Fill = clone, Width = this.myListBox.ActualWidth, Height = this.myListBox.ActualHeight };
        Border border = new Border { Background = Brushes.White, Width = this.myListBox.ActualWidth, Height = this.myListBox.ActualHeight };
        border.Child = rectangle;
        grid.Children.Add(border);
        Grid.SetRow(border, 1);

        scrollView.Width = this.myListBox.ActualWidth;
        scrollView.Height = this.myListBox.ActualHeight;
        scrollView.Content = grid;
        scrollView.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;

        return scrollView;
    }

这是我的 DocumentPaginator 实现中的 GetPage 覆盖:

public override DocumentPage GetPage(int pageNumber)
    {
        Page page = new Page();
        double z = 0.0;

        this.grid = new Grid();
        this.grid.RowDefinitions.Add(new RowDefinition());
        this.grid.RowDefinitions[0].Height = new GridLength(0, GridUnitType.Auto);

        this.grid.Children.Add(this.printViewer);
        Grid.SetRow(this.printViewer, 0);

        //Adjusting the vertical scroll offset depending on the page number
        if (pageNumber + 1 == 1) //if First Page
        {
            this.printViewer.ScrollToVerticalOffset(0);
            this.printViewer.UpdateLayout();
        }
        else if (pageNumber + 1 == _verticalPageCount) //if Last Page
        {
            if (this.printViewer.ScrollableHeight == 0) //If printing only single page and the contents fits only on one page
            {
                this.printViewer.ScrollToVerticalOffset(0);
                this.printViewer.UpdateLayout();

            }
            else if (this.printViewer.ScrollableHeight <= this.printViewer.Height) //If scrollconentheight is less or equal than scrollheight
            {
                this.printViewer.Height = this.printViewer.ScrollableHeight;
                this.printViewer.ScrollToEnd();
                this.printViewer.UpdateLayout();
            }
            else //if the scrollcontentheight is greater than scrollheight then set the scrollviewer height to be the remainder between scrollcontentheight and scrollheight
            {
                this.printViewer.Height = (this.printViewer.ScrollableHeight % this.printViewer.Height) + 5;
                this.printViewer.ScrollToEnd();
                this.printViewer.UpdateLayout();
            }
        }
        else //Other Pages
        {
            z = z + this.printViewer.Height;
            this.printViewer.ScrollToVerticalOffset(z);
            this.printViewer.UpdateLayout();
        }

        page.Content = this.grid; //put the grid into the page
        page.Arrange(new Rect(this.originalMargin.Left, this.originalMargin.Top, this.ContentSize.Width, this.ContentSize.Height));
        page.UpdateLayout();

        return new DocumentPage(page);
    }

有趣的是,如果我将矩形的填充更改为画笔而不是克隆,那么我不会收到异常并且输出的文件大小正确。

我花了一天多的时间尝试调试为什么这不起作用,我希望那里有人看到类似的问题或能够指出我犯的任何错误。

感谢您的任何回复。

【问题讨论】:

    标签: c# wpf printing xps


    【解决方案1】:

    我不得不放弃使用 VisualBrush 寻找解决方案。如果画笔的 Visual 中有一个 GroupBox,我永远无法让它生成 XPS 文件。它总是失败

    System.ArgumentException was unhandled by user code Message=Width and Height must be non-negative. Source=ReachFramework StackTrace: at System.Windows.Xps.Serialization.VisualSerializer.WriteTileBrush(String element, TileBrush brush, Rect bounds)

    解决方法是克隆应该放在 VisualBrush (Is there an easy/built-in way to get an exact copy (clone) of a XAML element?) 中的内容,并直接在 Grid 中使用它而不是 VisualBrush

    【讨论】:

    • 在这个领域似乎确实存在一些细微差别。我们最终使用 Teleriks 库来帮助渲染我们的 PDF
    【解决方案2】:

    在创建 VisualBrush 时是否检查了 myListBox 的 ActualWidth 和 ActualHeight 的值?我不知道 myListBox 是从哪里来的,但是如果在您生成 xps 文档时它没有呈现,您可能会遇到问题。您可以尝试manually force the control to render 看看是否有什么不同。

    【讨论】:

    • 我可以确认,在创建 VisualBrush 时,ActualHeight 和 ActualWidth 属性都是有效值,并且 myListBox 在打印时显示在应用程序中,因此它肯定会被渲染。我已经尝试显示我放入 VisualBrush 的矩形并且效果很好。令我困惑的部分是代码在将其发送到物理打印机时工作正常,但在将其发送到 XPS 驱动程序时却不行。
    • 您是否尝试过答案链接中建议的 RenderTargetBitmap 方法?也许问题是由于使用了 VisualBrush。
    • 感谢您的建议,但是我想找到一种不使用 RenderTargetBitmap 的方法,我们的原始方法使用了这种方法,我们发现输出模糊的问题加上应用程序会耗尽内存。
    【解决方案3】:

    我无法解决问题,但是使用此链接 Paginated printing of WPF visuals 我能够找到合适的解决方案,以允许在我的 WPF 应用程序中打印复杂的视觉效果。

    【讨论】:

      【解决方案4】:

      现在是 2016 年,但仍未修复。问题是使用TileBrush 或任何后代类型(在您的情况下为VisualBrush)。如果您使用绝对映射,它会起作用,它是导致问题的相对映射。自己计算最终大小并将Viewport设置为这个大小,ViewportUnits设置为Absolute。还要确保你不要使用Stretch

      【讨论】:

      • 我们实际上转而使用第三方库,最终打印为 PDF,因为客户改变了(谢天谢地)他们想要输出的文件格式的想法。不过,我会记住这一点,以备将来打印。
      • 我碰巧两者都需要。 :-) 实际上,现在打开 .NET 源代码,您可以检查出错的 WriteTileBrush() 函数。那里有另一个修复的评论,但这个肯定漏掉了。虽然从源代码中看不出问题到底出在哪里(它创建了几个Rects,实际大小取决于输入),但它确实给了我尝试以某种方式解决这些计算的想法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-21
      • 1970-01-01
      • 2011-04-17
      • 2012-11-01
      • 2010-10-04
      相关资源
      最近更新 更多