Is there a way to print documents (eg PDF) in .NET Maui?

I didn't find any built-in solution or working solution using free nuget package. Does anyone have experience with this issue, or can someone offer their own solution?

1

3 Answers

To be clear, .NET Maui does not have the print API to print documents (e.g. PDF or HTML). And there's a feature request: Printing UI for MAUI Windows/Android/iOS #9931 on Github, you can follow up there.

Below are the useful links that you can refer to:

2

There is no API present in MAUI to print; however, you can write native code for the print API. For Mac and iOS, you can use UIKIT and, for Windows, you can use Windows.Graphics and UI.Printing classes.

 public async void PrintImageMac(Stream img){ try { var data = NSData.FromStream(img); var uiimage = UIImage.LoadFromData(data); var printer = UIPrintInteractionController.SharedPrintController; if (printer == null) { Console.WriteLine("Printer is not connected"); } else { var printInfo = UIPrintInfo.PrintInfo; printInfo.OutputType = UIPrintInfoOutputType.General; printer.PrintInfo = printInfo; printer.PrintingItem = uiimage; var handler = new UIPrintInteractionCompletionHandler((printInteractionController, completed, error) => { if (completed) { Console.WriteLine("Printer Success"); } else if (!completed && error != null) { Console.WriteLine("Print Failed"); } }); CGRect frame = new CGRect(); frame.Size = uiimage.Size; printer.Present(true, handler); } } catch (Exception ex) { LogHandler.LogError(ex); } } private void PrintClickedEvent(object sender, EventArgs e) { try { var filepath = @"E:/sample.png" //filepath _printService = new PrintService(); var openFile = System.IO.File.OpenRead(filepath); #if MACCATALYST _printService.PrintImageMac(openFile); #elif WINDOWS _printService.Print(openFile, filepath, this.Window.Handler.PlatformView as Microsoft.UI.Xaml.Window); #endif } catch (Exception ex) { LogHandler.LogError(ex); } } 

This will work on Windows. Although it is working all print functionality is working fine, the only issue is previewOfpage is not been dislayed for the first time, but when it s called again then it is visible , so if anyone found something which i am missing then please let me know

public class PrintService { private PageDescription currentPageDescription; private UIElement printPreviewPages; private Canvas imagePanel = new(); private string _filePath; private Window _window; private string _fileName; private nint _hWnd; private PrintDocument printDocument; private IPrintDocumentSource printDocumentSource; private PrintManager printMan; private int _pageCount; private double marginWidth; private double marginHeight; private PrintTask printTask; private FrameworkElement firstPage; private PhotoSize photoSize; private Scaling photoScale; public async void Print(Stream inputStream, string filepath, Window nativeWindow) { _filePath = filepath; this._fileName = Path.GetFileName(_filePath); this._window = nativeWindow; this._hWnd = WinRT.Interop.WindowNative.GetWindowHandle(_window); var fileType = File.ReadAllBytes(filepath); try { await PrintWithCanvas(); } catch(Exception ex) { LogHandler.LogError(ex); } } private async Task PrintWithCanvas() { try { this.RegisterForPrint(); await PrintManagerInterop.ShowPrintUIForWindowAsync(_hWnd); } catch (Exception ex) { LogHandler.LogError(ex); } } private void RegisterForPrint() { try { printDocument = new PrintDocument(); printDocumentSource = printDocument.DocumentSource; printDocument.Paginate += CreatePrintPreviewPages; printDocument.GetPreviewPage += PrintDoc_GetPreviewPage; printDocument.AddPages += AddPrintPages; printMan = PrintManagerInterop.GetForWindow(_hWnd); printMan.PrintTaskRequested += PrintTask_Requested; } catch (Exception ex) { LogHandler.LogError(ex); } } private async void AddPrintPages(object sender, AddPagesEventArgs e) { try { await this.PrepareForPrint(); ((PrintDocument)sender).AddPagesComplete(); } catch { ((PrintDocument)sender).InvalidatePreview(); } } private async Task PrepareForPrint() { imagePanel.Children.Clear(); ApplicationLanguages.PrimaryLanguageOverride = CultureInfo.InvariantCulture.TwoLetterISOLanguageName; var imageCtrl = new Image(); BitmapImage src = new BitmapImage(new Uri(_filePath, UriKind.Absolute)); imageCtrl.Source = src; imageCtrl.Height = currentPageDescription.ViewablePageSize.Height / DeviceDisplay.Current.MainDisplayInfo.Density; imageCtrl.Width = currentPageDescription.ViewablePageSize.Width / DeviceDisplay.Current.MainDisplayInfo.Density; imageCtrl.HorizontalAlignment = Microsoft.UI.Xaml.HorizontalAlignment.Center; imageCtrl.VerticalAlignment = Microsoft.UI.Xaml.VerticalAlignment.Center; printDocument.AddPage(imageCtrl); } private async void PrintTask_Requested(PrintManager sender, PrintTaskRequestedEventArgs args) { printTask = args.Request.CreatePrintTask(_fileName, sourceRequestedArgs => { CustomizePrintTask(args, sourceRequestedArgs).GetAwaiter(); }); printTask.Completed += PrintTask_Completed1; } private void PrintTask_Completed1(PrintTask sender, PrintTaskCompletedEventArgs args) { printMan.PrintTaskRequested -= PrintTask_Requested; } private async Task CustomizePrintTask(PrintTaskRequestedEventArgs args, PrintTaskSourceRequestedArgs sourceRequestedArgs) { PrintTaskOptionDetails printDetailedOptions = PrintTaskOptionDetails.GetFromPrintTaskOptions(printTask.Options); printDetailedOptions.DisplayedOptions.Clear(); printDetailedOptions.DisplayedOptions.Add(Windows.Graphics.Printing.StandardPrintTaskOptions.MediaSize); printDetailedOptions.DisplayedOptions.Add(Windows.Graphics.Printing.StandardPrintTaskOptions.Copies); printDetailedOptions.DisplayedOptions.Add(Windows.Graphics.Printing.StandardPrintTaskOptions.ColorMode); // Create a new list option. PrintCustomItemListOptionDetails photoSize = printDetailedOptions.CreateItemListOption("photoSize", "Photo Size"); photoSize.AddItem("SizeFullPage", "Full Page"); photoSize.AddItem("Size4x6", "4 x 6 in"); photoSize.AddItem("Size5x7", "5 x 7 in"); photoSize.AddItem("Size8x10", "8 x 10 in"); printDetailedOptions.DisplayedOptions.Add("photoSize"); printTask.Options.Orientation = PrintOrientation.Portrait; sourceRequestedArgs.SetSource(printDocumentSource); } private async void PrintDetailedOptionsOptionChanged(PrintTaskOptionDetails sender, PrintTaskOptionChangedEventArgs args) { if (args.OptionId == null) { return; } string optionId = args.OptionId.ToString(); if (optionId == "photoSize") { IPrintOptionDetails photoSizeOption = sender.Options[optionId]; string photoSizeValue = photoSizeOption.Value as string; if (!string.IsNullOrEmpty(photoSizeValue)) { switch (photoSizeValue) { case "SizeFullPage": photoSize = PhotoSize.SizeFullPage; break; case "Size4x6": photoSize = PhotoSize.Size4x6; break; case "Size5x7": photoSize = PhotoSize.Size5x7; break; case "Size8x10": photoSize = PhotoSize.Size8x10; break; } } } if (optionId == "scaling") { IPrintOptionDetails scalingOption = sender.Options[optionId]; string scalingValue = scalingOption.Value as string; if (!string.IsNullOrEmpty(scalingValue)) { switch (scalingValue) { case "Crop": photoScale = Scaling.Crop; break; case "ShrinkToFit": photoScale = Scaling.ShrinkToFit; break; } } } } private async void CreatePrintPreviewPages(object sender, PaginateEventArgs e) { try { PrintDocument printDoc = (PrintDocument)sender; PageDescription pageDescription = new PageDescription(); //PrintTaskOptionDetails printDetailedOptions = PrintTaskOptionDetails.GetFromPrintTaskOptions(e.PrintTaskOptions); PrintPageDescription printPageDescription = e.PrintTaskOptions.GetPageDescription(0); pageDescription.Margin.Width = Math.Max( printPageDescription.ImageableRect.Left, printPageDescription.ImageableRect.Right - printPageDescription.PageSize.Width); pageDescription.Margin.Height = Math.Max( printPageDescription.ImageableRect.Top, printPageDescription.ImageableRect.Bottom - printPageDescription.PageSize.Height); pageDescription.ViewablePageSize.Width = printPageDescription.PageSize.Width - pageDescription.Margin.Width * 2; pageDescription.ViewablePageSize.Height = printPageDescription.PageSize.Height - pageDescription.Margin.Height * 2; switch (photoSize) { case PhotoSize.Size4x6: pageDescription.PictureViewSize.Width = 4 * DPI96; pageDescription.PictureViewSize.Height = 6 * DPI96; break; case PhotoSize.Size5x7: pageDescription.PictureViewSize.Width = 5 * DPI96; pageDescription.PictureViewSize.Height = 7 * DPI96; break; case PhotoSize.Size8x10: pageDescription.PictureViewSize.Width = 8 * DPI96; pageDescription.PictureViewSize.Height = 10 * DPI96; break; case PhotoSize.SizeFullPage: pageDescription.PictureViewSize.Width = pageDescription.ViewablePageSize.Width; pageDescription.PictureViewSize.Height = pageDescription.ViewablePageSize.Height; break; } if ((pageDescription.ViewablePageSize.Width > pageDescription.ViewablePageSize.Height) && (photoSize != PhotoSize.SizeFullPage)) { var swap = pageDescription.PictureViewSize.Width; pageDescription.PictureViewSize.Width = pageDescription.PictureViewSize.Height; pageDescription.PictureViewSize.Height = swap; } pageDescription.IsContentCropped = photoScale == Scaling.Crop; currentPageDescription = pageDescription; printDoc.SetPreviewPageCount(1, PreviewPageCountType.Intermediate); } catch (Exception ex) { LogHandler.LogError(ex); } } private async void PrintDoc_GetPreviewPage(object sender, GetPreviewPageEventArgs e) { int pageNumber = e.PageNumber; UIElement page; page = await GeneratePageAsync(1, currentPageDescription); printPreviewPages = page; PrintDocument printDoc = (PrintDocument)sender; printDoc.SetPreviewPage(pageNumber, page); } private async Task<UIElement> GeneratePageAsync(int photoNumber, PageDescription pageDescription) { Canvas viewablePage = new Canvas() { Width = pageDescription.ViewablePageSize.Width, Height = pageDescription.ViewablePageSize.Height }; var imageCtrl = new Image(); BitmapImage src = new BitmapImage(new Uri(_filePath, UriKind.Absolute)); imageCtrl.Source = src; imageCtrl.Height = currentPageDescription.ViewablePageSize.Height / DeviceDisplay.Current.MainDisplayInfo.Density; imageCtrl.Width = currentPageDescription.ViewablePageSize.Width / DeviceDisplay.Current.MainDisplayInfo.Density; imageCtrl.HorizontalAlignment = Microsoft.UI.Xaml.HorizontalAlignment.Center; imageCtrl.VerticalAlignment = Microsoft.UI.Xaml.VerticalAlignment.Center; viewablePage.Children.Add(imageCtrl); return viewablePage; } private static void Swap<T>(ref T v1, ref T v2) { T swap = v1; v1 = v2; v2 = swap; } public class PageDescription : IEquatable<PageDescription> { public Size Margin; public Size PageSize; public Size ViewablePageSize; public Size PictureViewSize; public bool IsContentCropped; public bool Equals(PageDescription other) { // Detect if PageSize changed bool equal = (Math.Abs(PageSize.Width - other.PageSize.Width) < double.Epsilon) && (Math.Abs(PageSize.Height - other.PageSize.Height) < double.Epsilon); if (equal) { equal = (Math.Abs(ViewablePageSize.Width - other.ViewablePageSize.Width) < double.Epsilon) && (Math.Abs(ViewablePageSize.Height - other.ViewablePageSize.Height) < double.Epsilon); } // Detect if PictureViewSize changed if (equal) { equal = (Math.Abs(PictureViewSize.Width - other.PictureViewSize.Width) < double.Epsilon) && (Math.Abs(PictureViewSize.Height - other.PictureViewSize.Height) < double.Epsilon); } // Detect if cropping changed if (equal) { equal = IsContentCropped == other.IsContentCropped; } return equal; } public enum PhotoSize : byte { SizeFullPage, Size4x6, Size5x7, Size8x10 } public enum Scaling : byte { ShrinkToFit, Crop } 

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.