Bijington Bijington - 6 months ago 45
C# Question

WPF printing/xps issue

I have written the following chunk of code that prints my ListBox perfectly when being sent to a physical printer, however when trying to send it to the XPS printer driver or using the XpsDocumentWriter class (I assume they use the same code under the hood) I receive the following exception:

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

The exception obviously points to an item not having a correct width/height however I have debugged the code when sending it to the different printers (physical and XPS driver) and I haven't been able to find any differences.

Below is how I create the visual to send to the printer:

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.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.SetRow(border, 1);

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

return scrollView;

Here is the GetPage override in my DocumentPaginator implementation:

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);

Grid.SetRow(this.printViewer, 0);

//Adjusting the vertical scroll offset depending on the page number
if (pageNumber + 1 == 1) //if First Page
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

else if (this.printViewer.ScrollableHeight <= this.printViewer.Height) //If scrollconentheight is less or equal than scrollheight
this.printViewer.Height = this.printViewer.ScrollableHeight;
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;
else //Other Pages
z = z + this.printViewer.Height;

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));

return new DocumentPage(page);

Interestingly if I change the Fill of rectangle to a Brush instead of clone then I do not receive the exception and the outputted file is the correct size.

I have spent over a day trying to debug why this isn't working and I am hoping that someone out there has either seen a similar issue or is able to point out any mistakes I am making.

Thanks for any responses.


I was unable to rectify the problem however using this link Paginated printing of WPF visuals I was able to find a suitable solution to allow printing of complicated visuals within my WPF application.