在多个页面上打印包含列表框的堆栈面板wpf

时间:2017-01-30 11:46:39

标签: c# wpf printing listbox

您好我打算打印一个包含列表框的StackPanel,该列表框可以包含无数个项目,因此需要打印多个页面。我在网上找到了这个代码,它运行正常。

public static FixedDocument GetFixedDocument(FrameworkElement toPrint, PrintDialog printDialog)
    {
        if (printDialog == null)
        {
            printDialog = new PrintDialog();
        }
        var capabilities = printDialog.PrintQueue.GetPrintCapabilities(printDialog.PrintTicket);
        var pageSize = new Size(printDialog.PrintableAreaWidth, printDialog.PrintableAreaHeight);
        var visibleSize = new Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight);
        var fixedDoc = new FixedDocument();
        //If the toPrint visual is not displayed on screen we neeed to measure and arrange it  
        toPrint.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
        toPrint.Arrange(new Rect(new Point(0, 0), toPrint.DesiredSize));
        //  
        var size = toPrint.DesiredSize;
        //Will assume for simplicity the control fits horizontally on the page  
        double yOffset = 0;
        while (yOffset < size.Height)
        {
            var vb = new VisualBrush(toPrint)
            {
                Stretch = Stretch.None,
                AlignmentX = AlignmentX.Left,
                AlignmentY = AlignmentY.Top,
                ViewboxUnits = BrushMappingMode.Absolute,
                TileMode = TileMode.None,
                Viewbox = new Rect(0, yOffset, visibleSize.Width, visibleSize.Height)
            };
            var pageContent = new PageContent();
            var page = new FixedPage();
            ((IAddChild)pageContent).AddChild(page);
            fixedDoc.Pages.Add(pageContent);
            page.Width = pageSize.Width;
            page.Height = pageSize.Height;
            var canvas = new Canvas();
            FixedPage.SetLeft(canvas, capabilities.PageImageableArea.OriginWidth);
            FixedPage.SetTop(canvas, capabilities.PageImageableArea.OriginHeight);
            canvas.Width = visibleSize.Width;
            canvas.Height = visibleSize.Height;
            canvas.Background = vb;
            page.Children.Add(canvas);
            yOffset += visibleSize.Height;
        }
        return fixedDoc;
    }

然而,这会导致列表框中的某些项目在页面底部被切断,并在下一页上继续(如下所示)。是否可以以任何方式修改此代码以确定页面的大小,如果当前的listboxitem不适合在下一页上启动的此页面上?所有这些都是新的,所以任何帮助都将非常感谢。Picture of issue

1 个答案:

答案 0 :(得分:0)

我有一个类似的任务,并提出了这个代码,它使用'虚拟'渲染器来预先确定元素的高度,然后将其添加到当前页面或创建一个新的。当然,这不是一个非常漂亮的解决方案,但它当时完成了这项工作。也许你可以采取某事。远离它。

Size A4Size = new Size(793.92, 1122.24);
Size InfiniteSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
var pages = new List<FrameworkElement>();
int pageNumber = 0;
var printDate = DateTime.Now;
var size = A4Size;

var currentPage = new Report(size, printDate);
currentPage.Render();

var listElements = new Queue<ElementsToPrint>(...);

var dummyRenderer = new Viewbox();
dummyRenderer.Child = currentPage;
dummyRenderer.Measure(InfiniteSize);
dummyRenderer.Arrange(new Rect(dummyRenderer.DesiredSize));
dummyRenderer.UpdateLayout();
var template = (DataTemplate)View.FindResource("ItemTemplate");

dummyRenderer.Child = null;

var availableHeight = currentPage.View.ActualHeight;

while (listElements.Count > 0)
{
    var elementToRender = listElements.Dequeue();
    dummyRenderer.Child = new ListViewItem()
    {
       Content = elementToRender,
       ContentTemplate = template,
       Foreground = Brushes.Black
    };
    dummyRenderer.Measure(InfiniteSize);
    dummyRenderer.Arrange(new Rect(dummyRenderer.DesiredSize));
    dummyRenderer.UpdateLayout();

    var renderedItem = (ListViewItem)dummyRenderer.Child;

    dummyRenderer.Child = null;


    var willItFit = availableHeight > renderedItem.ActualHeight;

    if (willItFit)
    {
        currentPage.DataListView.Items.Add(renderedItem);
        availableHeight -= renderedItem.ActualHeight;
    }
    else
    {
        dummyRenderer.Child = currentPage;
        dummyRenderer.Measure(InfiniteSize);
        dummyRenderer.Arrange(new Rect(dummyRenderer.DesiredSize));
        dummyRenderer.UpdateLayout();
        dummyRenderer.Child = null;

        pages.Add(currentPage);

        // Set up a new Page
        pageNumber++;

        currentPage = new DiaryReport(size,pageNumber,printDate,anonymous);

        dummyRenderer.Child = currentPage;
        dummyRenderer.Measure(InfiniteSize);
        dummyRenderer.Arrange(new Rect(dummyRenderer.DesiredSize));
        dummyRenderer.UpdateLayout();

        dummyRenderer.Child = null;

        availableHeight = currentPage.DataListView.ActualHeight;

        currentPage.DataListView.Items.Add(renderedItem);
        availableHeight -= renderedItem.ActualHeight;
    }