3

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

System.ArgumentException 未被用户代码处理 Message=Width 并且 Height 必须为非负数。Source=ReachFramework StackTrace:在 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);
    }

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

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

感谢您的任何回复。

4

4 回答 4

2

我不得不放弃用 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 的内容(是否有一种简单/内置的方法来获取 XAML 元素的精确副本(克隆)?)并直接在 Grid 而不是 VisualBrush 中使用它

于 2017-08-25T10:39:42.850 回答
1

创建 VisualBrush 时是否检查了 myListBox 的 ActualWidth 和 ActualHeight 的值?我不知道 myListBox 是从哪里来的,但是如果在您生成 xps 文档时它没有呈现,您可能会遇到问题。您可以尝试手动强制控件呈现并查看它是否有任何区别。

于 2012-12-18T16:17:30.410 回答
1

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

于 2014-03-27T14:19:53.223 回答
1

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

于 2016-11-21T09:24:12.703 回答