在 WPF 中打印 DataGrid 中的所有数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37698316/
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 13:50:24  来源:igfitidea点击:

Print all data in the DataGrid in WPF

c#.netwpfprintingdatagrid

提问by Gopi

I am working on WPF application. I have data in the DataGrid which I have to print all the data present in it. I tried like this...

我正在研究 WPF 应用程序。我在 DataGrid 中有数据,我必须打印其中存在的所有数据。我试过这样...

publicMainWindow()
    {
       InitializeComponent();

       DataTabledt = newDataTable();
       dt.Columns.Add("S.No");
       dt.Columns.Add("Name");
       dt.Columns.Add("Father's Name");
       dt.Columns.Add("D-O-B");
       dt.Columns.Add("Qualification");
       dt.Columns.Add("Gender");
       dt.Columns.Add("SSC %");
       dt.Columns.Add("+2 %");
       dt.Columns.Add("Graduation %");
       dt.Columns.Add("Work Experience");
       dt.Columns.Add("Company");

       object[] rowValues = {"01","Gopi","Ravi","31","Degree","M", "88","85", "80","2 Years","Blah Blah"};

       dt.Rows.Add(rowValues);
       dt.AcceptChanges();
       myGrid.DataContext = dt.DefaultView;
    }

       privatevoidPrint_Click(object sender, RoutedEventArgs e)
    {
       PrintDialogprintDlg = newPrintDialog();
       if ((bool)printDlg.ShowDialog().GetValueOrDefault())
        {
       Sizepagesize = newSize(printDlg.PrintableAreaWidth,printDlg.PrintableAreaHeight);
       myGrid.Measure(pagesize);
       myGrid.Arrange(newRect(5, 5, pagesize.Width, pagesize.Height));
            printDlg.PrintVisual(myGrid, "Personal Information");

        }
    }

when I click on print button it is printing only the data which we can see as below enter image description here

当我点击打印按钮时,它只打印我们可以看到的数据,如下所示 在此处输入图片说明

But in my case it is not printing work experience and company columns. How can I Print all the fields. Please help me out

但就我而言,它不是打印工作经验和公司专栏。如何打印所有字段。请帮帮我

EDIT: I think FlowDocument is used, but suppose I have 50 rows I cannot use FlowDocument. How can I Print in this case.

编辑:我认为使用 FlowDocument,但假设我有 50 行我不能使用 FlowDocument。在这种情况下我如何打印。

回答by Muhammad Mehdi

I have done code recently. It is tested code.It will print every datagrid with all records.It is easy and simple code.You would add a class. If you want to decorate a datagrid then go to PrintDG class then decorate it according to your own requirement.
Follow these steps.
Step1: Add these references on top.

我最近在做代码。它是经过测试的代码。它将打印包含所有记录的每个数据网格。这是简单而简单的代码。您将添加一个类。如果要装饰数据网格,请转到 PrintDG 类,然后根据自己的要求进行装饰。
按着这些次序。
步骤 1:在顶部添加这些引用。

    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Media;

    public  class PrintDG
    {
        public void printDG(DataGrid dataGrid, string title)
        {
            PrintDialog printDialog = new PrintDialog();

            if (printDialog.ShowDialog() == true)
            {
                FlowDocument fd = new FlowDocument();

                Paragraph p = new Paragraph(new Run(title));
                p.FontStyle = dataGrid.FontStyle;
                p.FontFamily = dataGrid.FontFamily;
                p.FontSize = 18;
                fd.Blocks.Add(p);

                Table table = new Table();
                TableRowGroup tableRowGroup = new TableRowGroup();
                TableRow r = new TableRow();
                fd.PageWidth = printDialog.PrintableAreaWidth;
                fd.PageHeight = printDialog.PrintableAreaHeight;
                fd.BringIntoView();

                fd.TextAlignment = TextAlignment.Center;
                fd.ColumnWidth = 500;
                table.CellSpacing = 0;

                var headerList = dataGrid.Columns.Select(e => e.Header.ToString()).ToList();
                List<dynamic> bindList = new List<dynamic>();

                for (int j = 0; j < headerList.Count; j++)
                {
                    r.Cells.Add(new TableCell(new Paragraph(new Run(headerList[j]))));
                    r.Cells[j].ColumnSpan = 4;
                    r.Cells[j].Padding = new Thickness(4);
                    r.Cells[j].BorderBrush = Brushes.Black;
                    r.Cells[j].FontWeight = FontWeights.Bold;
                    r.Cells[j].Background = Brushes.DarkGray;
                    r.Cells[j].Foreground = Brushes.White;
                    r.Cells[j].BorderThickness = new Thickness(1, 1, 1, 1);

                    var binding = (dataGrid.Columns[j] as DataGridBoundColumn).Binding as Binding;
                    bindList.Add(binding.Path.Path);
                }

                tableRowGroup.Rows.Add(r);
                table.RowGroups.Add(tableRowGroup);

                for (int i = 0; i < dataGrid.Items.Count; i++)
                {
                    dynamic row;

                    if (dataGrid.ItemsSource.ToString().ToLower() == "system.data.linqdataview")
                    { row = (DataRowView)dataGrid.Items.GetItemAt(i); }
                    else
                    {
                        row = (BalanceClient)dataGrid.Items.GetItemAt(i);
                    }

                    table.BorderBrush = Brushes.Gray;
                    table.BorderThickness = new Thickness(1, 1, 0, 0);
                    table.FontStyle = dataGrid.FontStyle;
                    table.FontFamily = dataGrid.FontFamily;
                    table.FontSize = 13;
                    tableRowGroup = new TableRowGroup();
                    r = new TableRow();

                    for (int j = 0; j < row.Row.ItemArray.Count(); j++)
                    {
                        if (dataGrid.ItemsSource.ToString().ToLower() == "system.data.linqdataview")
                        {
                            r.Cells.Add(new TableCell(new Paragraph(new Run(row.Row.ItemArray[j].ToString()))));
                        }
                        else
                        {
                            r.Cells.Add(new TableCell(new Paragraph(new Run(row.GetType().GetProperty(bindList[j]).GetValue(row, null)))));
                        }

                        r.Cells[j].ColumnSpan = 4;
                        r.Cells[j].Padding = new Thickness(4);
                        r.Cells[j].BorderBrush = Brushes.DarkGray;
                        r.Cells[j].BorderThickness = new Thickness(0, 0, 1, 1);
                    }

                    tableRowGroup.Rows.Add(r);
                    table.RowGroups.Add(tableRowGroup);
                }

                fd.Blocks.Add(table);
                printDialog.PrintDocument(((IDocumentPaginatorSource)fd).DocumentPaginator, "");
            }
        }
    }

Step2: Then go to print button click event and create object of PrintDG class then call printDG pass to It two parameters datagridname and title.
Like :

Step2:然后去打印按钮点击事件并创建PrintDG类的对象然后调用printDG传递给它两个参数datagridname和title。
喜欢 :

    private void print_button_Click(object sender, RoutedEventArgs e)
    {
        PrintDG print = new PrintDG();
        print.printDG(datagridName, "Title");
    }

If any error occurs during execution tell me and I will solve It.This is running code only, you need copy and paste.
Edited:
I declared row as dynamic. The dynamic keyword decides at run time which type to instantiate, either DataTable or another.

如果在执行过程中发生任何错误,请告诉我,我会解决它。这只是运行代码,您需要复制和粘贴。
编辑:
我将行声明为动态。dynamic 关键字在运行时决定实例化哪种类型,DataTable 或其他。

回答by Kadi Okba abdelmoumen

I work with This :

我和这个一起工作:

  // Author : Kadi Okba
public class WpfPrinting
{
    public const double cm = 37;
    public double Margin = 0.5 * cm;
    public double PageWidth = 21 * cm;
    public double PageHeight = 29 * cm;
    public double RowHeight = 0.7 * cm;
    public bool PageNumberVisibility = true;
    public bool DateVisibility = true;
    public double FontSize = 14;
    public double HeaderFontSize = 14;
    public bool IsBold = false;
    public void PrintDataGrid(FrameworkElement header, DataGrid grid, FrameworkElement footer, PrintDialog printDialog)
    {
        if (header == null) { header = new FrameworkElement(); header.Width = 1; header.Height = 1; }
        if (footer == null) { footer = new FrameworkElement(); footer.Width = 1; footer.Height = 1; }
        if (grid == null) return;

        Size pageSize = new Size(PageWidth, PageHeight);

        FixedDocument fixedDoc = new FixedDocument();
        fixedDoc.DocumentPaginator.PageSize = pageSize;

        double GridActualWidth = grid.ActualWidth == 0 ? grid.Width : grid.ActualWidth;

        double PageWidthWithMargin = pageSize.Width - Margin * 2;
        double PageHeightWithMargin = pageSize.Height - Margin * 2;



        // scale the header  
        double headerScale = (header?.Width ?? 0) / PageWidthWithMargin;
        double headerWidth = PageWidthWithMargin;
        double headerHeight = (header?.Height ?? 0) * headerScale;
        header.Height = headerHeight;
        header.Width = headerWidth;
        // scale the footer  
        double footerScale = (footer?.Width ?? 0) / PageWidthWithMargin;
        double footerWidth = PageWidthWithMargin;
        double footerHeight = (footer?.Height ?? 0) * footerScale;
        footer.Height = footerHeight;
        footer.Width = footerWidth;

        int pageNumber = 1;
        string Now = DateTime.Now.ToShortDateString();

        //add the header 
        FixedPage fixedPage = new FixedPage();
        fixedPage.Background = Brushes.White;
        fixedPage.Width = pageSize.Width;
        fixedPage.Height = pageSize.Height;

        FixedPage.SetTop(header, Margin);
        FixedPage.SetLeft(header, Margin);

        fixedPage.Children.Add(header);
        // its like cursor for current page Height to start add grid rows
        double CurrentPageHeight = headerHeight + 1 * cm;
        int lastRowIndex = 0;
        bool IsFooterAdded = false;

        for (;;)
        {
            int AvaliableRowNumber;


            var SpaceNeededForRestRows = (CurrentPageHeight + (grid.Items.Count - lastRowIndex) * RowHeight);

            //To avoid printing the footer in a separate page
            if (SpaceNeededForRestRows > (pageSize.Height - footerHeight - Margin) && (SpaceNeededForRestRows < (pageSize.Height - Margin)))
                AvaliableRowNumber = (int)((pageSize.Height - CurrentPageHeight - Margin - footerHeight) / RowHeight);
            // calc the Avaliable Row acording to CurrentPageHeight
            else AvaliableRowNumber = (int)((pageSize.Height - CurrentPageHeight - Margin) / RowHeight);

            // create new page except first page cause we created it prev
            if (pageNumber > 1)
            {
                fixedPage = new FixedPage();
                fixedPage.Background = Brushes.White;
                fixedPage.Width = pageSize.Width;
                fixedPage.Height = pageSize.Height;
            }

            // create new data grid with  columns width and binding
            DataGrid gridToAdd;
            gridToAdd = GetDataGrid(grid, GridActualWidth, PageWidthWithMargin);


            FixedPage.SetTop(gridToAdd, CurrentPageHeight); // top margin
            FixedPage.SetLeft(gridToAdd, Margin); // left margin

            // add the avaliable rows to the cuurent grid 
            for (int i = lastRowIndex; i < grid.Items.Count && i < AvaliableRowNumber + lastRowIndex; i++)
            {
                gridToAdd.Items.Add(grid.Items[i]);
            }
            lastRowIndex += gridToAdd.Items.Count + 1;

            // add date
            TextBlock dateText = new TextBlock();
            if (DateVisibility) dateText.Visibility = Visibility.Visible;
            else dateText.Visibility = Visibility.Hidden;
            dateText.Text = Now;

            // add page number
            TextBlock PageNumberText = new TextBlock();
            if (PageNumberVisibility) PageNumberText.Visibility = Visibility.Visible;
            else PageNumberText.Visibility = Visibility.Hidden;
            PageNumberText.Text = "Page : " + pageNumber;

            FixedPage.SetTop(dateText, PageHeightWithMargin);
            FixedPage.SetLeft(dateText, Margin);

            FixedPage.SetTop(PageNumberText, PageHeightWithMargin);
            FixedPage.SetLeft(PageNumberText, PageWidthWithMargin - PageNumberText.Text.Length * 10);

            fixedPage.Children.Add(gridToAdd);
            fixedPage.Children.Add(dateText);
            fixedPage.Children.Add(PageNumberText);

            // calc Current Page Height to know the rest Height of this page
            CurrentPageHeight += gridToAdd.Items.Count * RowHeight;

            // all grid rows added
            if (lastRowIndex >= grid.Items.Count)
            {
                // if footer have space it will be added to the same page
                if (footerHeight < (PageHeightWithMargin - CurrentPageHeight))
                {
                    FixedPage.SetTop(footer, CurrentPageHeight + Margin);
                    FixedPage.SetLeft(footer, Margin);

                    fixedPage.Children.Add(footer);
                    IsFooterAdded = true;
                }
            }

            fixedPage.Measure(pageSize);
            fixedPage.Arrange(new Rect(new Point(), pageSize));
            fixedPage.UpdateLayout();

            PageContent pageContent = new PageContent();
            ((IAddChild)pageContent).AddChild(fixedPage);
            fixedDoc.Pages.Add(pageContent);

            pageNumber++;
            // go to start position : New page Top
            CurrentPageHeight = Margin;

            // this mean that lastRowIndex >= grid.Items.Count  and the footer dont have enough space
            if (lastRowIndex >= grid.Items.Count && !IsFooterAdded)
            {
                FixedPage ffixedPage = new FixedPage();
                ffixedPage.Background = Brushes.White;
                ffixedPage.Width = pageSize.Width;
                ffixedPage.Height = pageSize.Height;

                FixedPage.SetTop(footer, Margin);
                FixedPage.SetLeft(footer, Margin);

                TextBlock fdateText = new TextBlock();
                if (DateVisibility) fdateText.Visibility = Visibility.Visible;
                else fdateText.Visibility = Visibility.Hidden;
                dateText.Text = Now;

                TextBlock fPageNumberText = new TextBlock();
                if (PageNumberVisibility) fPageNumberText.Visibility = Visibility.Visible;
                else fPageNumberText.Visibility = Visibility.Hidden;
                fPageNumberText.Text = "Page : " + pageNumber;

                FixedPage.SetTop(fdateText, PageHeightWithMargin);
                FixedPage.SetLeft(fdateText, Margin);

                FixedPage.SetTop(fPageNumberText, PageHeightWithMargin);
                FixedPage.SetLeft(fPageNumberText, PageWidthWithMargin - PageNumberText.ActualWidth);

                ffixedPage.Children.Add(footer);
                ffixedPage.Children.Add(fdateText);
                ffixedPage.Children.Add(fPageNumberText);

                ffixedPage.Measure(pageSize);
                ffixedPage.Arrange(new Rect(new Point(), pageSize));
                ffixedPage.UpdateLayout();

                PageContent fpageContent = new PageContent();
                ((IAddChild)fpageContent).AddChild(ffixedPage);
                fixedDoc.Pages.Add(fpageContent);
                IsFooterAdded = true;
            }

            if (IsFooterAdded)
            {
                break;
            }
        }
        PrintFixedDocument(fixedDoc, printDialog);
    }
    private DataGrid GetDataGrid(DataGrid grid, double GridActualWidth, double PageWidthWithMargin)
    {
        DataGrid printed = new DataGrid();


        // styling the grid
        Style rowStyle = new Style(typeof(DataGridRow));
        rowStyle.Setters.Add(new Setter(Control.BackgroundProperty, Brushes.White));
        rowStyle.Setters.Add(new Setter(Control.FontSizeProperty, FontSize));
        if (IsBold) rowStyle.Setters.Add(new Setter(Control.FontWeightProperty, FontWeights.Bold));
        rowStyle.Setters.Add(new Setter(Control.HeightProperty, RowHeight));


        Style columnStyle = new Style(typeof(DataGridColumnHeader));
        columnStyle.Setters.Add(new Setter(Control.FontSizeProperty, HeaderFontSize));
        columnStyle.Setters.Add(new Setter(Control.HorizontalContentAlignmentProperty, HorizontalAlignment.Center));
        columnStyle.Setters.Add(new Setter(Control.BorderThicknessProperty, new Thickness(0, 0.5, 0, 1.5)));
        columnStyle.Setters.Add(new Setter(Control.BackgroundProperty, Brushes.White));
        columnStyle.Setters.Add(new Setter(Control.BorderBrushProperty, Brushes.Black));
        columnStyle.Setters.Add(new Setter(Control.FontWeightProperty, FontWeights.SemiBold));


        printed.RowStyle = rowStyle;

        printed.VerticalGridLinesBrush = Brushes.Black;
        printed.HorizontalGridLinesBrush = Brushes.Black;
        printed.FontFamily = new FontFamily("Arial");

        printed.RowBackground = Brushes.White;
        printed.Background = Brushes.White;
        printed.Foreground = Brushes.Black;
        // get the columns of grid 
        foreach (var column in grid.Columns)
        {
            if (column.Visibility != Visibility.Visible) continue;
            DataGridTextColumn textColumn = new DataGridTextColumn();
            textColumn.HeaderStyle = columnStyle;
            textColumn.Header = column.Header;
            textColumn.Width = column.ActualWidth / GridActualWidth * PageWidthWithMargin;
            textColumn.Binding = ((DataGridTextColumn)column).Binding;
            printed.Columns.Add(textColumn);
        }
        printed.BorderBrush = Brushes.Black;


        return printed;
    }

    public void PrintFixedDocument(FixedDocument fixedDoc, PrintDialog printDialog)
    {
        XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(printDialog.PrintQueue);
        writer.Write(fixedDoc, printDialog.PrintTicket);
    }
}

回答by niwreg

This is related to Kadi Okba's answer (I can't comment due to my reputation):

这与 Kadi Okba 的回答有关(由于我的声誉,我无法发表评论):

The line lastRowIndex += gridToAdd.Items.Count + 1;caused problems for me. Due to incrementing by one, he skips a DataGridRow when opening a new/second page which is then missing on my printout.

这条线lastRowIndex += gridToAdd.Items.Count + 1;给我带来了问题。由于递增 1,他在打开新/第二页时跳过了 DataGridRow,然后在我的打印输出中丢失了该页。

lastRowIndex += gridToAdd.Items.Count;works well for me.

lastRowIndex += gridToAdd.Items.Count;对我来说效果很好。