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

标签 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;
    }

然而,这会导致列表框的某些项目在页面底部被截断并在下一页继续(如下所示)。是否可以以任何方式修改此代码以确定页面的大小,如果当前列表框项目不适合此页面,它会从下一页开始吗?这一切都很新,所以任何帮助将不胜感激。 Picture of issue

最佳答案

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

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

关于c# - 在多个页面上打印包含列表框的堆栈面板 wpf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41935154/

相关文章:

wpf - ListBox 中的水平单选按钮

Python print 函数不返回更新后的变量

C# : Unable to print data as unicode characters from MYSQL database

wpf - 如何在 XAML 的路径中转义字符 '&'?

google-chrome - 在 Chrome 中打印收据 - 质量差

c# - 验证 ABN(澳大利亚商业编号)

c# - 通过 C# 导入 Python 库?

c# - 内部企业 AD(事件目录)

c# - session 过期后从数据库中删除它吗?

c# - 如何重用 WPF 用户控件但更改绑定(bind)属性?