简体   繁体   English

打印多页 xaml 控件

[英]Print multiple pages of xaml controls

I'm trying to implement a WPF Print function.我正在尝试实现 WPF 打印功能。 It's working as long as the user doesnt want to print more than fits to one page.只要用户不想打印超过一页的大小,它就可以工作。 My Application enables the user to create xaml in runtime.我的应用程序使用户能够在运行时创建 xaml。 Now i want to also enable him to print the xaml controls he created.现在我还想让他打印他创建的 xaml 控件。

I have checked the total height of all xaml controls, devided by the pageheight and ceiled that number, so i know how many pages i have to print.我已经检查了所有 xaml 控件的总高度,除以 pageheight 并限制了该数字,所以我知道我必须打印多少页。

Next I'm creating a List of FrameworkElements for each page (see logic below) and store every List (each stands for one page) in an array.接下来,我将为每个页面创建一个 FrameworkElements 列表(请参见下面的逻辑)并将每个列表(每个列表都代表一个页面)存储在一个数组中。

At the end i want to create a preview which contains every page and enables the user to print all pages.最后,我想创建一个包含每个页面的预览,并使用户能够打印所有页面。 In order to do that i have to put the pages together to a Document, but i dont know how.为了做到这一点,我必须将页面放在一个文档中,但我不知道如何。 Please take a look at my code:请看一下我的代码:

Package package = Package.Open("test.xps", FileMode.Create);

        // Create new xps document based on the package opened

        XpsDocument doc = new XpsDocument(package);

        // Create an instance of XpsDocumentWriter for the document

        XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(doc);

        // Write the canvas (as Visual) to the document

        double height = element.ActualHeight;
        double width = element.ActualWidth;
        System.Windows.Controls.PrintDialog printDlg = new System.Windows.Controls.PrintDialog();
        Size pageSize = new Size(printDlg.PrintableAreaWidth, printDlg.PrintableAreaHeight);
        int pageCount = (int)Math.Ceiling(height / pageSize.Height);


        if (pageSize.Height < height) {
            var grid = element as Grid;
            var children = grid.Children;
            List<FrameworkElement>[] pages = new List<FrameworkElement>[pageCount-1];
            int i = 0;
            double currentHeight = 0;

            foreach (FrameworkElement c in children) {


                currentHeight += c.RenderSize.Height;


                if (currentHeight < pageSize.Height) {

                    pages[i] = new List<FrameworkElement>();
                    pages[i].Add(c);
                }
                else {
                    i++;
                    currentHeight = 0;
                    pages[i] = new List<FrameworkElement>();
                    pages[i].Add(c);
                }
            }
            for (int j = 0; j < pageCount; j++) {
                var collator = writer.CreateVisualsCollator();
                collator.BeginBatchWrite();
                foreach (FrameworkElement c in pages[j]) {


                    collator.Write(c);


                }
                collator.EndBatchWrite();
            }
        }


        doc.Close();

        package.Close();

        string filename = @"C:\Users\rzimmermann\Documents\Visual Studio 2012\Projects\MvvmLightPrintFunction\MvvmLightPrintFunction\bin\Debug\test.xps";

        DocumentViewer viewer = new DocumentViewer();

        doc = new XpsDocument(filename, FileAccess.Read);

        viewer.Document = doc.GetFixedDocumentSequence();

        Window ShowWindow = new Window();

        ShowWindow.Width = 400;

        ShowWindow.Height = 300;

        ShowWindow.Content = viewer;

        ShowWindow.Show();

@kenny is right you need to use the FixedPages. @kenny 是对的,您需要使用 FixedPages。 For a great tutorial pleas see: http://www.nbdtech.com/Blog/archive/2009/04/20/wpf-printing-part-2-the-fixed-document.aspx有关精彩教程,请参阅: http : //www.nbdtech.com/Blog/archive/2009/04/20/wpf-printing-part-2-the-fixed-document.aspx

As far as adding pages to a document you can do it like so:至于向文档添加页面,您可以这样做:

doc.Pages.Add(page1Content);
doc.Pages.Add(page2Content);

//ect. //等。

 ... PrintDialog dialog = new PrintDialog();

        //dialog.PrintVisual(this.scrollCheckCardinfo, "");
        Nullable<Boolean> print = dialog.ShowDialog();
        if (print == true)
        {
            Grid DynamicGrid = new Grid();
            DynamicGrid.Margin = new Thickness(100, 50, 0, 0);
            RowDefinition gridRow1 = new RowDefinition();
            gridRow1.Height = new GridLength(45);
            RowDefinition gridRow2 = new RowDefinition();
            DynamicGrid.RowDefinitions.Add(gridRow1);
            DynamicGrid.RowDefinitions.Add(gridRow2);
            TextBlock txtBlock1 = new TextBlock();
            txtBlock1.Text = "Printed by xyz " + DateTime.Now.ToString();
            txtBlock1.FontSize = 14;
            txtBlock1.FontWeight = FontWeights.Bold;
            txtBlock1.VerticalAlignment = VerticalAlignment.Top;

            Grid.SetRow(txtBlock1, 0);
            Grid.SetRow(this.scrollCheckCardinfo, 1);
            DynamicGrid.Children.Add(txtBlock1);
            DynamicGrid.Children.Add(CloneXaml(this.scrollCheckCardinfo));
            dialog.PrintVisual(DynamicGrid, "xyz");

        }...
     public static T CloneXaml<T>(T source)
    {
        string xaml = XamlWriter.Save(source);
        StringReader sr = new StringReader(xaml);
        XmlReader xr = XmlReader.Create(sr);
        return (T)XamlReader.Load(xr);
    }

this.scrollCheckCardinfo is a Grid. this.scrollCheckCardinfo 是一个网格。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM