wpf 打印多页 xaml 控件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23220952/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 11:36:17  来源:igfitidea点击:

Print multiple pages of xaml controls

c#wpfxamlprinting

提问by user3292642

I'm trying to implement a WPF Print function. 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. Now i want to also enable him to print the xaml controls he created.

我正在尝试实现 WPF 打印功能。只要用户不想打印超过一页的大小,它就可以工作。我的应用程序使用户能够在运行时创建 xaml。现在我还想让他打印他创建的 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();

回答by Jarod Kientz

@kenny is right you need to use the FixedPages. For a great tutorial pleas see: http://www.nbdtech.com/Blog/archive/2009/04/20/wpf-printing-part-2-the-fixed-document.aspx

@kenny 是对的,您需要使用 FixedPages。有关精彩教程,请参阅: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.

//等。

回答by huse.ckr

 ... 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 是一个网格。