我编写了以下代码块,可以在发送到物理打印机时完美地打印我的ListBox,但是在尝试将其发送到XPS打印机驱动程序或使用XpsDocumentWriter类时(我假设它们使用相同的代码)我收到以下例外:
System.ArgumentException未被用户代码处理 消息=宽度和高度必须是非负的。 来源= ReachFramework 堆栈跟踪: 在System.Windows.Xps.Serialization.VisualSerializer.WriteTileBrush(String element,TileBrush brush,Rect bounds)
该异常显然指向一个没有正确宽度/高度的项目但是我在将代码发送到不同的打印机(物理和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);
}
有趣的是,如果我将矩形的填充更改为Brush而不是clone,那么我不会收到异常并且输出的文件大小正确。
我花了一天多的时间试图调试为什么这不起作用,我希望那里有人看到过类似的问题,或者能够指出我正在犯的任何错误。
感谢您的回复。
答案 0 :(得分:1)
在创建VisualBrush时,您是否检查过myListBox的ActualWidth和ActualHeight的值?我不知道myListBox来自哪里,但如果在生成xps文档时它没有呈现,则可能会遇到问题。您可以尝试manually force the control to render,看看它是否有所不同。
答案 1 :(得分:1)
我无法纠正这个问题,但使用此链接Paginated printing of WPF visuals我能找到一个合适的解决方案,允许在我的WPF应用程序中打印复杂的视觉效果。
答案 2 :(得分:1)
现在是2016年,它还没有修复。问题是在您的情况下使用TileBrush
或任何后代类型(VisualBrush
)。如果使用绝对映射,它可以工作,它是导致问题的相对映射。自己计算最终尺寸并将Viewport
设置为此尺寸,ViewportUnits
设为Absolute
。另外,请确保您不使用Stretch
。
答案 3 :(得分:1)
我不得不放弃使用VisualBrush找到解决方案。如果Visual for the Brush中有一个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