1

我正在尝试将TextBox我的 XAML 页面上的内容打印到打印机。

我在这条线上遇到了一个例外:

PrintingRoot.Children.Add(firstPage);

对于上面的行,它说“对象引用未设置为对象的实例。”。我不确定为什么,因为我正在向它添加一个页面。

该行所在的方法是:

    public void PreparetPrintContent()
    {
        if (firstPage == null)
        {
            firstPage = new MainPage();
        }

        PrintingRoot.Children.Add(firstPage);
        PrintingRoot.InvalidateMeasure();
        PrintingRoot.UpdateLayout();
    }

我究竟做错了什么?我怎样才能把我的 TextBox 的内容打印到打印机上?

我使用了我在http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/a6296590-21bc-4e1f-a61f-7cf2352f1e1e上找到的代码


完整代码:

private async void Print_Click_1(object sender, RoutedEventArgs e)
        {
            MainPage pg = FindVisualParent<MainPage>(this);
            IList<Frame> fl = FindVisualChildList<Frame>(pg);
            //TextBox to = FindVisualChild<TextBox>(fl[0], "textContent");
            TextBox tp = FindVisualChild<TextBox>(firstPage, "textContent");
            //tp.Text = to.Text;
            // Don't act when in snapped mode
            if (ApplicationView.Value != ApplicationViewState.Snapped)
            {
                await Windows.Graphics.Printing.PrintManager.ShowPrintUIAsync();
            }
        }

        private static IList<childItemType> FindVisualChildList<childItemType>(DependencyObject obj) where childItemType : DependencyObject
        {
            IList<childItemType> list;
            list = new List<childItemType>();
            FindVisualChildList<childItemType>(obj, list);
            return list;
        }
        private static void FindVisualChildList<childItemType>(DependencyObject obj, IList<childItemType> list) where childItemType : DependencyObject
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child != null && child is childItemType)
                    list.Add((childItemType)child);
                else
                    FindVisualChildList<childItemType>(child, list);
            }
            return;
        }
        private static childItemType FindVisualChild<childItemType>(DependencyObject obj, string name) where childItemType : FrameworkElement
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child is childItemType && ((FrameworkElement)child).Name == name)
                    return (childItemType)child;
                else
                {
                    childItemType childOfChild = FindVisualChild<childItemType>(child, name);
                    if (childOfChild != null)
                        return childOfChild;
                }
            }
            return null;
        }
        private static parentItemType FindVisualParent<parentItemType>(DependencyObject o) where parentItemType : FrameworkElement
        {
            if (o == null)
                return null;
            if ((o is parentItemType))
                return o as parentItemType;
            return FindVisualParent<parentItemType>(VisualTreeHelper.GetParent(o));
        }

        public void PreparetPrintContent()
        {
            if (firstPage == null)
            {
                firstPage = new MainPage();
            }

            PrintingRoot.Children.Add(firstPage);
            PrintingRoot.InvalidateMeasure();
            PrintingRoot.UpdateLayout();
        }

        private async void InvokePrintButtonClick(object sender, RoutedEventArgs e)
        {
            MainPage pg = FindVisualParent<MainPage>(this);
            IList<Frame> fl = FindVisualChildList<Frame>(pg);
            TextBox to = FindVisualChild<TextBox>(fl[2], "textContent");
            TextBox tp = FindVisualChild<TextBox>(firstPage, "textContent");
            tp.Text = to.Text;
            // Don't act when in snapped mode
            if (ApplicationView.Value != ApplicationViewState.Snapped)
            {
                await Windows.Graphics.Printing.PrintManager.ShowPrintUIAsync();
            }
        }

        #region Application Content Size Constants given in percents ( normalized )

        /// <summary>
        /// The percent of app's margin width, content is set at 85% (0.85) of the area's width
        /// </summary>
        protected const double ApplicationContentMarginLeft = 0.075;

        /// <summary>
        /// The percent of app's margin height, content is set at 94% (0.94) of tha area's height
        /// </summary>
        protected const double ApplicationContentMarginTop = 0.03;

        #endregion

        /// <summary>
        /// A pointer back to the main page which is used to gain access to the input and output frames and their content. 
        /// </summary>
        protected MainPage rootPage = null;

        /// <summary>
        /// PrintDocument is used to prepare the pages for printing. 
        /// Prepare the pages to print in the handlers for the Paginate, GetPreviewPage, and AddPages events.
        /// </summary>
        protected PrintDocument printDocument = null;

        /// <summary>
        /// Marker interface for document source
        /// </summary>
        protected IPrintDocumentSource printDocumentSource = null;

        /// <summary>
        /// A list of UIElements used to store the print preview pages.  This gives easy access
        /// to any desired preview page.
        /// </summary>
        internal List<UIElement> printPreviewPages = null;

        /// <summary>
        /// First page in the printing-content series
        /// From this "virtual sized" paged content is split(text is flowing) to "printing pages"
        /// </summary>
        protected FrameworkElement firstPage;

        /// <summary>
        /// Factory method for every scenario that will create/generate print content specific to each scenario
        /// For scenarios 1-5: it will create the first page from which content will flow
        /// Scenario 6 uses a different approach
        /// </summary>
        //protected virtual void PreparetPrintContent() {}

        public void BasePrintPage()
        {
            printPreviewPages = new List<UIElement>();
        }

        /// <summary>
        ///  Printing root property on each input page.
        /// </summary>
        protected virtual Canvas PrintingRoot
        {
            get
            {
                return FindName("printingRoot") as Canvas;
            }
        }

        /// <summary>
        /// This is the event handler for PrintManager.PrintTaskRequested.
        /// </summary>
        /// <param name="sender">PrintManager</param>
        /// <param name="e">PrintTaskRequestedEventArgs </param>
        protected virtual void PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs e)
        {
            PrintTask printTask = null;
            printTask = e.Request.CreatePrintTask("C# Printing SDK Sample", sourceRequested =>
                {
                    // Print Task event handler is invoked when the print job is completed.
                    printTask.Completed += async (s, args) =>
                    {
                        // Notify the user when the print operation fails.
                        if (args.Completion == PrintTaskCompletion.Failed)
                        {
                            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                            {
                                //rootPage.NotifyUser("Failed to print.", NotifyType.ErrorMessage);
                            });
                        }
                    };

                    sourceRequested.SetSource(printDocumentSource);
                });
        } 

        /// <summary>
        /// This function registers the app for printing with Windows and sets up the necessary event handlers for the print process.
        /// </summary>
        protected void RegisterForPrinting()
        {
            // Create the PrintDocument.
            printDocument = new PrintDocument();

            // Save the DocumentSource.
            printDocumentSource = printDocument.DocumentSource;

            // Add an event handler which creates preview pages.
            printDocument.Paginate += CreatePrintPreviewPages;

            // Add an event handler which provides a specified preview page.
            printDocument.GetPreviewPage += GetPrintPreviewPage;

            // Add an event handler which provides all final print pages.
            printDocument.AddPages += AddPrintPages;

            // Create a PrintManager and add a handler for printing initialization.
            PrintManager printMan = PrintManager.GetForCurrentView();
            printMan.PrintTaskRequested += PrintTaskRequested;

            // Initialize print content for this scenario
            PreparetPrintContent();
        }

        /// <summary>
        /// This function unregisters the app for printing with Windows.
        /// </summary>
        protected virtual void UnregisterForPrinting()
        {
            if (printDocument == null)
                return;

            printDocument.Paginate -= CreatePrintPreviewPages;
            printDocument.GetPreviewPage -= GetPrintPreviewPage;
            printDocument.AddPages -= AddPrintPages;

            // Remove the handler for printing initialization.
            PrintManager printMan = PrintManager.GetForCurrentView();
            printMan.PrintTaskRequested -= PrintTaskRequested;

            PrintingRoot.Children.Clear();
        }

        protected event EventHandler pagesCreated;

        /// <summary>
        /// This is the event handler for PrintDocument.Paginate. It creates print preview pages for the app.
        /// </summary>
        /// <param name="sender">PrintDocument</param>
        /// <param name="e">Paginate Event Arguments</param>
        protected virtual void CreatePrintPreviewPages(object sender, PaginateEventArgs e)
        {
            // Clear the cache of preview pages 
            printPreviewPages.Clear();

            // Clear the printing root of preview pages
            PrintingRoot.Children.Clear();

            // This variable keeps track of the last RichTextBlockOverflow element that was added to a page which will be printed
            RichTextBlockOverflow lastRTBOOnPage;

            // Get the PrintTaskOptions
            PrintTaskOptions printingOptions = ((PrintTaskOptions)e.PrintTaskOptions);

            // Get the page description to deterimine how big the page is
            PrintPageDescription pageDescription = printingOptions.GetPageDescription(0);

            // We know there is at least one page to be printed. passing null as the first parameter to
            // AddOnePrintPreviewPage tells the function to add the first page.
            lastRTBOOnPage = AddOnePrintPreviewPage(null, pageDescription);

            // We know there are more pages to be added as long as the last RichTextBoxOverflow added to a print preview
            // page has extra content
            while (lastRTBOOnPage.HasOverflowContent && lastRTBOOnPage.Visibility == Windows.UI.Xaml.Visibility.Visible)
            {
                lastRTBOOnPage = AddOnePrintPreviewPage(lastRTBOOnPage, pageDescription);
            }

            if (pagesCreated != null)
            {
                pagesCreated.Invoke(printPreviewPages, null);
            }

            PrintDocument printDoc = (PrintDocument)sender;

            // Report the number of preview pages created
            printDoc.SetPreviewPageCount(printPreviewPages.Count, PreviewPageCountType.Intermediate);
        }

        /// <summary>
        /// This is the event handler for PrintDocument.GetPrintPreviewPage. It provides a specific print preview page,
        /// in the form of an UIElement, to an instance of PrintDocument. PrintDocument subsequently converts the UIElement
        /// into a page that the Windows print system can deal with.
        /// </summary>
        /// <param name="sender">PrintDocument</param>
        /// <param name="e">Arguments containing the preview requested page</param>
        protected virtual void GetPrintPreviewPage(object sender, GetPreviewPageEventArgs e)
        {
            PrintDocument printDoc = (PrintDocument)sender;

            printDoc.SetPreviewPage(e.PageNumber, printPreviewPages[e.PageNumber - 1]);
        }

        /// <summary>
        /// This is the event handler for PrintDocument.AddPages. It provides all pages to be printed, in the form of
        /// UIElements, to an instance of PrintDocument. PrintDocument subsequently converts the UIElements
        /// into a pages that the Windows print system can deal with.
        /// </summary>
        /// <param name="sender">PrintDocument</param>
        /// <param name="e">Add page event arguments containing a print task options reference</param>
        protected virtual void AddPrintPages(object sender, AddPagesEventArgs e)
        {
            // Loop over all of the preview pages and add each one to  add each page to be printied
            for (int i = 0; i < printPreviewPages.Count; i++)
            {
                // We should have all pages ready at this point...
                printDocument.AddPage(printPreviewPages[i]);
            }

            PrintDocument printDoc = (PrintDocument)sender;

            // Indicate that all of the print pages have been provided
            printDoc.AddPagesComplete();
        }

        /// <summary>
        /// This function creates and adds one print preview page to the internal cache of print preview
        /// pages stored in printPreviewPages.
        /// </summary>
        /// <param name="lastRTBOAdded">Last RichTextBlockOverflow element added in the current content</param>
        /// <param name="printPageDescription">Printer's page description</param>
        protected virtual RichTextBlockOverflow AddOnePrintPreviewPage(RichTextBlockOverflow lastRTBOAdded, PrintPageDescription printPageDescription)
        {
            // XAML element that is used to represent to "printing page"
            FrameworkElement page;

            // The link container for text overflowing in this page
            RichTextBlockOverflow textLink;

            // Check if this is the first page ( no previous RichTextBlockOverflow)
            if (lastRTBOAdded == null)
            {
                // If this is the first page add the specific scenario content
                page = firstPage;
            }
            else
            {
                // Flow content (text) from previous pages
                page = new ContinuationPage(lastRTBOAdded);
            }

            // Set "paper" width
            page.Width = printPageDescription.PageSize.Width;
            page.Height = printPageDescription.PageSize.Height;

            Grid printableArea = (Grid)page.FindName("printableArea");

            // Get the margins size
            // If the ImageableRect is smaller than the app provided margins use the ImageableRect
            double marginWidth = Math.Max(printPageDescription.PageSize.Width - printPageDescription.ImageableRect.Width, printPageDescription.PageSize.Width * ApplicationContentMarginLeft * 2);
            double marginHeight = Math.Max(printPageDescription.PageSize.Height - printPageDescription.ImageableRect.Height, printPageDescription.PageSize.Height * ApplicationContentMarginTop * 2);

            // Set-up "printable area" on the "paper"
            printableArea.Width = firstPage.Width - marginWidth;
            printableArea.Height = firstPage.Height - marginHeight;

            // Add the (newley created) page to the printing root which is part of the visual tree and force it to go
            // through layout so that the linked containers correctly distribute the content inside them.            
            PrintingRoot.Children.Add(page);
            //PrintingRoot.InvalidateMeasure();
            PrintingRoot.UpdateLayout();

            // Find the last text container and see if the content is overflowing
            textLink = (RichTextBlockOverflow)page.FindName("continuationPageLinkedContainer");

            // Check if this is the last page
            if (!textLink.HasOverflowContent && textLink.Visibility == Windows.UI.Xaml.Visibility.Visible)
            {
                StackPanel footer = (StackPanel)page.FindName("footer");
                footer.Visibility = Windows.UI.Xaml.Visibility.Visible;
            }

            // Add the page to the page preview collection
            printPreviewPages.Add(page);

            return textLink;
        }

        #region Navigation

        #endregion
4

1 回答 1

2

可能不是firstPage那为空的。还要检查PrintingRootandChildren元素。很可能,Children还没有更新,所以试图Add()抛出这个异常。

于 2013-04-01T15:32:20.100 回答