Printing datagrid rowdetails ignores code changes in LoadingRowDetails method

Mike Whalley 71 Reputation points
2021-01-25T19:13:17.547+00:00

I have a WPF datagrid showing a list of members. When a member is selected, rowdetails open showing further details for that member. I catch the LoadingRowDetails event in order to make certain format changes in the rowdetails, depending on the nature of the member selected, e.g:

        private void dgdCustomersListing_LoadingRowDetails(object sender, DataGridRowDetailsEventArgs e)
        {
            Customer selectedCustomer = (Customer)dgdCustomersListing.SelectedItem;
            Border subscriptionBox = e.DetailsElement.FindName("gbxSubscription") as Border;
            Label subLabel = e.DetailsElement.FindName("lblSub") as Label;
            Label nextDue = e.DetailsElement.FindName("lblNextDue") as Label;
            Label period = e.DetailsElement.FindName("lblPeriod") as Label;
            Label currency = e.DetailsElement.FindName("lblCurrency") as Label;
            currency.Content = customerType + " currency :";
            subscriptionBox.Visibility = customerType == "Tenant" || customerType == "Member" ? Visibility.Visible : Visibility.Collapsed;
            if (customerType == "Tenant")
            {
                subLabel.Content = "Rent amount :";
                nextDue.Content = "Next due :";
                period.Content = "Rent payable :";
            }

In order to print a 'snapshot' of the row details of a single Member, I change the ItemsSource of the DataGrid to show only the Member selected:

dgdCustomersListing.ItemsSource = searchCustomers.Skip(selectedRow).Take(1);
dgdCustomersListing.RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.Visible;

so that only that record (with its rowdetails showing) will print.

To print, I call either:

PrintMethods.PrintHelper.PrintNoPreview(printDlg, PrintMethods.PrintHelper.GetFixedDocument(grdCustomerListing, printDlg));

or:
PrintMethods.PrintHelper.ShowPrintPreview(PrintMethods.PrintHelper.GetFixedDocument(grdCustomerListing, printDlg));

which then use the following usual methods:

public class PrintMethods
    {
        public static class PrintHelper
        {
            public static FixedDocument GetFixedDocument(FrameworkElement toPrint, PrintDialog printDialog)
            {
                Thickness margin = new Thickness(0);
                var capabilities = printDialog.PrintQueue.GetPrintCapabilities(printDialog.PrintTicket);
                var pageSize = new Size(printDialog.PrintableAreaWidth, printDialog.PrintableAreaHeight);
                var visibleSize = new Size(capabilities.PageImageableArea.ExtentWidth-margin.Left-margin.Right, capabilities.PageImageableArea.ExtentHeight-margin.Top-margin.Bottom);
                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));
                toPrint.UpdateLayout();
                //  
                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;
            }

            public static void ShowPrintPreview(FixedDocument fixedDoc)
            {
                var wnd = new Window();
                var viewer = new DocumentViewer();
                viewer.Document = fixedDoc;
                wnd.Content = viewer;
                wnd.ShowDialog();
            }

            public static void PrintNoPreview(PrintDialog printDialog, FixedDocument fixedDoc)
            {
                try
                {
                    printDialog.PrintDocument(fixedDoc.DocumentPaginator, "PMM Report");
                }
                catch (System.Runtime.CompilerServices.RuntimeWrappedException)
                {
                    MessageBox.Show("You are trying to over-write an existing PDF document of the same name which is open." +
                        "\n\nPlease close the old document and try again, or save the new document with a new name.", "Save to PDF failed", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

As you can see, both print and print preview methods create the same fixed document from the same canvas.

This all works fine on screen, when printing to a PDF and when using the print preview method (ShowPrintPreview), all of which show (and print) a faithful representation of the rowdetails, as amended by the LoadingRowDetails event. However, when I print to a printer directly (using the PrintNoPreview method), the rowdetails printed reflect the original XAML code, ignoring the changes made following the LoadingRowDetails event.

I either need to force the user to use print preview, or set up multiple rowdetails in XAML for each possible Member type.

Can anyone explain why the physical print is ignoring the changes made by the LoadingRowDetails event method and reverting to the original XAML?

Many thanks

XAML
XAML
A language based on Extensible Markup Language (XML) that enables developers to specify a hierarchy of objects with a set of properties and logic.
809 questions
{count} votes

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.